VirtualBox

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

最後變更 在這個檔案從85887是 85887,由 vboxsync 提交於 5 年 前

IPRT/RTDvm: Added RTDVMVOLIDX_HOST index. bugref:9224

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 21.5 KB
 
1/* $Id: dvmbsdlabel.cpp 85887 2020-08-25 21:05:37Z vboxsync $ */
2/** @file
3 * IPRT Disk Volume Management API (DVM) - BSD disklabel format backend.
4 */
5
6/*
7 * Copyright (C) 2011-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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/string.h>
32#include <iprt/asm.h>
33#include "internal/dvm.h"
34
35
36/*********************************************************************************************************************************
37* Structures and Typedefs *
38*********************************************************************************************************************************/
39
40/*
41 * Below are the on disk structures of a bsd disklabel as found in
42 * /usr/include/sys/disklabel.h from a FreeBSD system.
43 *
44 * Everything is stored in little endian on the disk.
45 */
46
47/** BSD disklabel magic. */
48#define RTDVM_BSDLBL_MAGIC UINT32_C(0x82564557)
49/** Maximum number of partitions in the label. */
50#define RTDVM_BSDLBL_MAX_PARTITIONS 8
51
52/**
53 * A BSD disk label partition.
54 */
55typedef struct BsdLabelPartition
56{
57 /** Number of sectors in the partition. */
58 uint32_t cSectors;
59 /** Start sector. */
60 uint32_t offSectorStart;
61 /** Filesystem fragment size. */
62 uint32_t cbFsFragment;
63 /** Filesystem type. */
64 uint8_t bFsType;
65 /** Filesystem fragments per block. */
66 uint8_t cFsFragmentsPerBlock;
67 /** Filesystem cylinders per group. */
68 uint16_t cFsCylPerGroup;
69} BsdLabelPartition;
70AssertCompileSize(BsdLabelPartition, 16);
71/** Pointer to a BSD disklabel partition structure. */
72typedef BsdLabelPartition *PBsdLabelPartition;
73
74/**
75 * On disk BSD label structure.
76 */
77typedef struct BsdLabel
78{
79 /** Magic identifying the BSD disk label. */
80 uint32_t u32Magic;
81 /** Drive type */
82 uint16_t u16DriveType;
83 /** Subtype depending on the drive type above. */
84 uint16_t u16SubType;
85 /** Type name. */
86 uint8_t abTypeName[16];
87 /** Pack identifier. */
88 uint8_t abPackName[16];
89 /** Number of bytes per sector. */
90 uint32_t cbSector;
91 /** Number of sectors per track. */
92 uint32_t cSectorsPerTrack;
93 /** Number of tracks per cylinder. */
94 uint32_t cTracksPerCylinder;
95 /** Number of data cylinders pre unit. */
96 uint32_t cDataCylindersPerUnit;
97 /** Number of data sectors per cylinder. */
98 uint32_t cDataSectorsPerCylinder;
99 /** Number of data sectors per unit (unit as in disk drive?). */
100 uint32_t cSectorsPerUnit;
101 /** Number of spare sectors per track. */
102 uint16_t cSpareSectorsPerTrack;
103 /** Number of spare sectors per cylinder. */
104 uint16_t cSpareSectorsPerCylinder;
105 /** Number of alternate cylinders per unit. */
106 uint32_t cSpareCylindersPerUnit;
107 /** Rotational speed of the disk drive in rotations per minute. */
108 uint16_t cRotationsPerMinute;
109 /** Sector interleave. */
110 uint16_t uSectorInterleave;
111 /** Sector 0 skew, per track. */
112 uint16_t uSectorSkewPerTrack;
113 /** Sector 0 skew, per cylinder. */
114 uint16_t uSectorSkewPerCylinder;
115 /** Head switch time in us. */
116 uint32_t usHeadSwitch;
117 /** Time of a track-to-track seek in us. */
118 uint32_t usTrackSeek;
119 /** Flags. */
120 uint32_t fFlags;
121 /** Drive type sepcific information. */
122 uint32_t au32DriveData[5];
123 /** Reserved. */
124 uint32_t au32Reserved[5];
125 /** The magic number again. */
126 uint32_t u32Magic2;
127 /** Checksum (xor of the whole structure). */
128 uint16_t u16ChkSum;
129 /** Number of partitions in the array. */
130 uint16_t cPartitions;
131 /** Boot area size in bytes. */
132 uint32_t cbBootArea;
133 /** Maximum size of the filesystem super block. */
134 uint32_t cbFsSuperBlock;
135 /** The partition array. */
136 BsdLabelPartition aPartitions[RTDVM_BSDLBL_MAX_PARTITIONS];
137} BsdLabel;
138AssertCompileSize(BsdLabel, 148 + RTDVM_BSDLBL_MAX_PARTITIONS * 16);
139/** Pointer to a BSD disklabel structure. */
140typedef BsdLabel *PBsdLabel;
141
142/**
143 * BSD disk label volume manager data.
144 */
145typedef struct RTDVMFMTINTERNAL
146{
147 /** Pointer to the underlying disk. */
148 PCRTDVMDISK pDisk;
149 /** Number of used partitions. */
150 uint32_t cPartitions;
151 /** Saved BSD disklabel structure. */
152 BsdLabel DiskLabel;
153} RTDVMFMTINTERNAL;
154/** Pointer to the MBR volume manager. */
155typedef RTDVMFMTINTERNAL *PRTDVMFMTINTERNAL;
156
157/**
158 * MBR volume data.
159 */
160typedef struct RTDVMVOLUMEFMTINTERNAL
161{
162 /** Pointer to the volume manager. */
163 PRTDVMFMTINTERNAL pVolMgr;
164 /** Partition table entry index. */
165 uint32_t idxEntry;
166 /** Start offset of the volume. */
167 uint64_t offStart;
168 /** Size of the volume. */
169 uint64_t cbVolume;
170 /** Pointer to the raw partition table entry. */
171 PBsdLabelPartition pBsdPartitionEntry;
172} RTDVMVOLUMEFMTINTERNAL;
173/** Pointer to an MBR volume. */
174typedef RTDVMVOLUMEFMTINTERNAL *PRTDVMVOLUMEFMTINTERNAL;
175
176/** Converts a LBA number to the byte offset. */
177#define RTDVM_BSDLBL_LBA2BYTE(lba, disk) ((lba) * (disk)->cbSector)
178/** Converts a Byte offset to the LBA number. */
179#define RTDVM_BSDLBL_BYTE2LBA(lba, disk) ((lba) / (disk)->cbSector)
180
181/**
182 * Calculates the checksum of the entire bsd disklabel structure.
183 *
184 * @returns The checksum.
185 * @param pBsdLabel BSD disklabel to get the checksum for.
186 */
187static uint16_t rtDvmFmtBsdLblDiskLabelChkSum(PBsdLabel pBsdLabel)
188{
189 uint16_t uChkSum = 0;
190 uint16_t *pCurr = (uint16_t *)pBsdLabel;
191 uint16_t *pEnd = (uint16_t *)&pBsdLabel->aPartitions[pBsdLabel->cPartitions];
192
193 while (pCurr < pEnd)
194 uChkSum ^= *pCurr++;
195
196 return uChkSum;
197}
198
199/**
200 * Converts a partition entry to the host endianness.
201 *
202 * @returns nothing.
203 * @param pPartition The partition to decode.
204 */
205static void rtDvmFmtBsdLblDiskLabelDecodePartition(PBsdLabelPartition pPartition)
206{
207 pPartition->cSectors = RT_LE2H_U32(pPartition->cSectors);
208 pPartition->offSectorStart = RT_LE2H_U32(pPartition->offSectorStart);
209 pPartition->cbFsFragment = RT_LE2H_U32(pPartition->cbFsFragment);
210 pPartition->cFsCylPerGroup = RT_LE2H_U16(pPartition->cFsCylPerGroup);
211}
212
213/**
214 * Converts the on disk BSD label to the host endianness.
215 *
216 * @returns Whether the given label structure is a valid BSD disklabel.
217 * @param pBsdLabel Pointer to the BSD disklabel to decode.
218 */
219static bool rtDvmFmtBsdLblDiskLabelDecode(PBsdLabel pBsdLabel)
220{
221 pBsdLabel->u32Magic = RT_LE2H_U32(pBsdLabel->u32Magic);
222 pBsdLabel->u16DriveType = RT_LE2H_U16(pBsdLabel->u16DriveType);
223 pBsdLabel->u16SubType = RT_LE2H_U16(pBsdLabel->u16SubType);
224 pBsdLabel->cbSector = RT_LE2H_U32(pBsdLabel->cbSector);
225 pBsdLabel->cSectorsPerTrack = RT_LE2H_U32(pBsdLabel->cSectorsPerTrack);
226 pBsdLabel->cTracksPerCylinder = RT_LE2H_U32(pBsdLabel->cTracksPerCylinder);
227 pBsdLabel->cDataCylindersPerUnit = RT_LE2H_U32(pBsdLabel->cDataCylindersPerUnit);
228 pBsdLabel->cDataSectorsPerCylinder = RT_LE2H_U32(pBsdLabel->cDataSectorsPerCylinder);
229 pBsdLabel->cSectorsPerUnit = RT_LE2H_U32(pBsdLabel->cSectorsPerUnit);
230 pBsdLabel->cSpareSectorsPerTrack = RT_LE2H_U16(pBsdLabel->cSpareSectorsPerTrack);
231 pBsdLabel->cSpareSectorsPerCylinder = RT_LE2H_U16(pBsdLabel->cSpareSectorsPerCylinder);
232 pBsdLabel->cSpareCylindersPerUnit = RT_LE2H_U32(pBsdLabel->cSpareCylindersPerUnit);
233 pBsdLabel->cRotationsPerMinute = RT_LE2H_U16(pBsdLabel->cRotationsPerMinute);
234 pBsdLabel->uSectorInterleave = RT_LE2H_U16(pBsdLabel->uSectorInterleave);
235 pBsdLabel->uSectorSkewPerTrack = RT_LE2H_U16(pBsdLabel->uSectorSkewPerTrack);
236 pBsdLabel->uSectorSkewPerCylinder = RT_LE2H_U16(pBsdLabel->uSectorSkewPerCylinder);
237 pBsdLabel->usHeadSwitch = RT_LE2H_U16(pBsdLabel->usHeadSwitch);
238 pBsdLabel->usTrackSeek = RT_LE2H_U16(pBsdLabel->usTrackSeek);
239 pBsdLabel->fFlags = RT_LE2H_U32(pBsdLabel->fFlags);
240
241 for (unsigned i = 0; i < RT_ELEMENTS(pBsdLabel->au32DriveData); i++)
242 pBsdLabel->au32DriveData[i] = RT_LE2H_U32(pBsdLabel->au32DriveData[i]);
243 for (unsigned i = 0; i < RT_ELEMENTS(pBsdLabel->au32Reserved); i++)
244 pBsdLabel->au32Reserved[i] = RT_LE2H_U32(pBsdLabel->au32Reserved[i]);
245
246 pBsdLabel->u32Magic2 = RT_LE2H_U32(pBsdLabel->u32Magic2);
247 pBsdLabel->u16ChkSum = RT_LE2H_U16(pBsdLabel->u16ChkSum);
248 pBsdLabel->cPartitions = RT_LE2H_U16(pBsdLabel->cPartitions);
249 pBsdLabel->cbBootArea = RT_LE2H_U32(pBsdLabel->cbBootArea);
250 pBsdLabel->cbFsSuperBlock = RT_LE2H_U32(pBsdLabel->cbFsSuperBlock);
251
252 /* Check the magics now. */
253 if ( pBsdLabel->u32Magic != RTDVM_BSDLBL_MAGIC
254 || pBsdLabel->u32Magic2 != RTDVM_BSDLBL_MAGIC
255 || pBsdLabel->cPartitions != RTDVM_BSDLBL_MAX_PARTITIONS)
256 return false;
257
258 /* Convert the partitions array. */
259 for (unsigned i = 0; i < RT_ELEMENTS(pBsdLabel->aPartitions); i++)
260 rtDvmFmtBsdLblDiskLabelDecodePartition(&pBsdLabel->aPartitions[i]);
261
262 /* Check the checksum now. */
263 uint16_t u16ChkSumSaved = pBsdLabel->u16ChkSum;
264
265 pBsdLabel->u16ChkSum = 0;
266 if (u16ChkSumSaved != rtDvmFmtBsdLblDiskLabelChkSum(pBsdLabel))
267 return false;
268
269 pBsdLabel->u16ChkSum = u16ChkSumSaved;
270 return true;
271}
272
273static DECLCALLBACK(int) rtDvmFmtBsdLblProbe(PCRTDVMDISK pDisk, uint32_t *puScore)
274{
275 BsdLabel DiskLabel;
276 int rc = VINF_SUCCESS;
277
278 *puScore = RTDVM_MATCH_SCORE_UNSUPPORTED;
279
280 if (pDisk->cbDisk >= sizeof(BsdLabel))
281 {
282 /* Read from the disk and check for the disk label structure. */
283 rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &DiskLabel, sizeof(BsdLabel));
284 if ( RT_SUCCESS(rc)
285 && rtDvmFmtBsdLblDiskLabelDecode(&DiskLabel))
286 *puScore = RTDVM_MATCH_SCORE_PERFECT;
287 }
288 return rc;
289}
290
291static DECLCALLBACK(int) rtDvmFmtBsdLblOpen(PCRTDVMDISK pDisk, PRTDVMFMT phVolMgrFmt)
292{
293 int rc = VINF_SUCCESS;
294 PRTDVMFMTINTERNAL pThis = NULL;
295
296 pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL));
297 if (pThis)
298 {
299 pThis->pDisk = pDisk;
300 pThis->cPartitions = 0;
301
302 /* Read from the disk and check for the disk label structure. */
303 rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &pThis->DiskLabel, sizeof(BsdLabel));
304 if ( RT_SUCCESS(rc)
305 && rtDvmFmtBsdLblDiskLabelDecode(&pThis->DiskLabel))
306 {
307 /* Count number of used entries. */
308 for (unsigned i = 0; i < pThis->DiskLabel.cPartitions; i++)
309 if (pThis->DiskLabel.aPartitions[i].cSectors)
310 pThis->cPartitions++;
311
312 *phVolMgrFmt = pThis;
313 }
314 else
315 {
316 RTMemFree(pThis);
317 rc = VERR_INVALID_MAGIC;
318 }
319 }
320 else
321 rc = VERR_NO_MEMORY;
322
323 return rc;
324}
325
326static DECLCALLBACK(int) rtDvmFmtBsdLblInitialize(PCRTDVMDISK pDisk, PRTDVMFMT phVolMgrFmt)
327{
328 NOREF(pDisk); NOREF(phVolMgrFmt);
329 return VERR_NOT_IMPLEMENTED;
330}
331
332static DECLCALLBACK(void) rtDvmFmtBsdLblClose(RTDVMFMT hVolMgrFmt)
333{
334 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
335
336 pThis->pDisk = NULL;
337 pThis->cPartitions = 0;
338 RT_ZERO(pThis->DiskLabel);
339 RTMemFree(pThis);
340}
341
342static DECLCALLBACK(int) rtDvmFmtBsdLblQueryRangeUse(RTDVMFMT hVolMgrFmt,
343 uint64_t off, uint64_t cbRange,
344 bool *pfUsed)
345{
346 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
347
348 NOREF(cbRange);
349
350 if (off <= RTDVM_BSDLBL_LBA2BYTE(1, pThis->pDisk))
351 *pfUsed = true;
352 else
353 *pfUsed = false;
354
355 return VINF_SUCCESS;
356}
357
358static DECLCALLBACK(uint32_t) rtDvmFmtBsdLblGetValidVolumes(RTDVMFMT hVolMgrFmt)
359{
360 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
361 return pThis->cPartitions;
362}
363
364static DECLCALLBACK(uint32_t) rtDvmFmtBsdLblGetMaxVolumes(RTDVMFMT hVolMgrFmt)
365{
366 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
367 return pThis->DiskLabel.cPartitions;
368}
369
370/**
371 * Creates a new volume.
372 *
373 * @returns IPRT status code.
374 * @param pThis The MBR volume manager data.
375 * @param pbBsdLblEntry The raw MBR entry data.
376 * @param idx The index in the partition table.
377 * @param phVolFmt Where to store the volume data on success.
378 */
379static int rtDvmFmtBsdLblVolumeCreate(PRTDVMFMTINTERNAL pThis, PBsdLabelPartition pBsdPartitionEntry,
380 uint32_t idx, PRTDVMVOLUMEFMT phVolFmt)
381{
382 int rc = VINF_SUCCESS;
383 PRTDVMVOLUMEFMTINTERNAL pVol = (PRTDVMVOLUMEFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEFMTINTERNAL));
384
385 if (pVol)
386 {
387 pVol->pVolMgr = pThis;
388 pVol->idxEntry = idx;
389 pVol->pBsdPartitionEntry = pBsdPartitionEntry;
390 pVol->offStart = (uint64_t)pBsdPartitionEntry->offSectorStart * pThis->DiskLabel.cbSector;
391 pVol->cbVolume = (uint64_t)pBsdPartitionEntry->cSectors * pThis->DiskLabel.cbSector;
392
393 *phVolFmt = pVol;
394 }
395 else
396 rc = VERR_NO_MEMORY;
397
398 return rc;
399}
400
401static DECLCALLBACK(int) rtDvmFmtBsdLblQueryFirstVolume(RTDVMFMT hVolMgrFmt, PRTDVMVOLUMEFMT phVolFmt)
402{
403 int rc = VINF_SUCCESS;
404 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
405
406 if (pThis->cPartitions != 0)
407 {
408 /* Search for the first non empty entry. */
409 for (unsigned i = 0; i < pThis->DiskLabel.cPartitions; i++)
410 {
411 if (pThis->DiskLabel.aPartitions[i].cSectors)
412 {
413 rc = rtDvmFmtBsdLblVolumeCreate(pThis, &pThis->DiskLabel.aPartitions[i], i, phVolFmt);
414 break;
415 }
416 }
417 }
418 else
419 rc = VERR_DVM_MAP_EMPTY;
420
421 return rc;
422}
423
424static DECLCALLBACK(int) rtDvmFmtBsdLblQueryNextVolume(RTDVMFMT hVolMgrFmt, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUMEFMT phVolFmtNext)
425{
426 int rc = VERR_DVM_MAP_NO_VOLUME;
427 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
428 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
429 PBsdLabelPartition pBsdPartitionEntry = pVol->pBsdPartitionEntry + 1;
430
431 for (unsigned i = pVol->idxEntry + 1; i < pThis->DiskLabel.cPartitions; i++)
432 {
433 if (pBsdPartitionEntry->cSectors)
434 {
435 rc = rtDvmFmtBsdLblVolumeCreate(pThis, pBsdPartitionEntry, i, phVolFmtNext);
436 break;
437 }
438 pBsdPartitionEntry++;
439 }
440
441 return rc;
442}
443
444static DECLCALLBACK(void) rtDvmFmtBsdLblVolumeClose(RTDVMVOLUMEFMT hVolFmt)
445{
446 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
447
448 pVol->pVolMgr = NULL;
449 pVol->offStart = 0;
450 pVol->cbVolume = 0;
451 pVol->pBsdPartitionEntry = NULL;
452
453 RTMemFree(pVol);
454}
455
456static DECLCALLBACK(uint64_t) rtDvmFmtBsdLblVolumeGetSize(RTDVMVOLUMEFMT hVolFmt)
457{
458 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
459
460 return pVol->cbVolume;
461}
462
463static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryName(RTDVMVOLUMEFMT hVolFmt, char **ppszVolName)
464{
465 NOREF(hVolFmt); NOREF(ppszVolName);
466 return VERR_NOT_SUPPORTED;
467}
468
469static DECLCALLBACK(RTDVMVOLTYPE) rtDvmFmtBsdLblVolumeGetType(RTDVMVOLUMEFMT hVolFmt)
470{
471 NOREF(hVolFmt);
472 return RTDVMVOLTYPE_UNKNOWN;
473}
474
475static DECLCALLBACK(uint64_t) rtDvmFmtBsdLblVolumeGetFlags(RTDVMVOLUMEFMT hVolFmt)
476{
477 NOREF(hVolFmt);
478 return DVMVOLUME_F_CONTIGUOUS;
479}
480
481static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryRange(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffStart, uint64_t *poffLast)
482{
483 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
484 *poffStart = pVol->offStart;
485 *poffLast = pVol->offStart + pVol->cbVolume - 1;
486 return VINF_SUCCESS;
487}
488
489static DECLCALLBACK(bool) rtDvmFmtBsdLblVolumeIsRangeIntersecting(RTDVMVOLUMEFMT hVolFmt,
490 uint64_t offStart, size_t cbRange,
491 uint64_t *poffVol,
492 uint64_t *pcbIntersect)
493{
494 bool fIntersect = false;
495 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
496
497 if (RTDVM_RANGE_IS_INTERSECTING(pVol->offStart, pVol->cbVolume, offStart))
498 {
499 fIntersect = true;
500 *poffVol = offStart - pVol->offStart;
501 *pcbIntersect = RT_MIN(cbRange, pVol->offStart + pVol->cbVolume - offStart);
502 }
503
504 return fIntersect;
505}
506
507/** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */
508static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryTableLocation(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffTable, uint64_t *pcbTable)
509{
510 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
511 *poffTable = RTDVM_BSDLBL_LBA2BYTE(1, pVol->pVolMgr->pDisk);
512 *pcbTable = RT_ALIGN_Z(sizeof(BsdLabel), pVol->pVolMgr->pDisk->cbSector);
513 return VINF_SUCCESS;
514}
515
516/** @copydoc RTDVMFMTOPS::pfnVolumeGetIndex */
517static DECLCALLBACK(uint32_t) rtDvmFmtBsdLblVolumeGetIndex(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex)
518{
519 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
520 switch (enmIndex)
521 {
522 case RTDVMVOLIDX_USER_VISIBLE:
523 case RTDVMVOLIDX_ALL:
524 case RTDVMVOLIDX_LINUX:
525 return pVol->idxEntry + 1;
526 case RTDVMVOLIDX_IN_TABLE:
527 return pVol->idxEntry;
528
529 case RTDVMVOLIDX_INVALID:
530 case RTDVMVOLIDX_HOST:
531 case RTDVMVOLIDX_END:
532 case RTDVMVOLIDX_32BIT_HACK:
533 break;
534 /* no default! */
535 }
536 AssertFailed();
537 return UINT32_MAX;
538}
539
540/** @copydoc RTDVMFMTOPS::pfnVolumeQueryProp */
541static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryProp(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty,
542 void *pvBuf, size_t cbBuf, size_t *pcbBuf)
543{
544 switch (enmProperty)
545 {
546 case RTDVMVOLPROP_MBR_FIRST_CYLINDER:
547 case RTDVMVOLPROP_MBR_FIRST_HEAD:
548 case RTDVMVOLPROP_MBR_FIRST_SECTOR:
549 case RTDVMVOLPROP_MBR_LAST_CYLINDER:
550 case RTDVMVOLPROP_MBR_LAST_HEAD:
551 case RTDVMVOLPROP_MBR_LAST_SECTOR:
552 case RTDVMVOLPROP_MBR_TYPE:
553 case RTDVMVOLPROP_GPT_TYPE:
554 case RTDVMVOLPROP_GPT_UUID:
555 return VERR_NOT_SUPPORTED;
556
557 case RTDVMVOLPROP_INVALID:
558 case RTDVMVOLPROP_END:
559 case RTDVMVOLPROP_32BIT_HACK:
560 break;
561 /* no default! */
562 }
563 RT_NOREF(hVolFmt, pvBuf, cbBuf, pcbBuf);
564 return VERR_NOT_SUPPORTED;
565}
566
567static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeRead(RTDVMVOLUMEFMT hVolFmt, uint64_t off, void *pvBuf, size_t cbRead)
568{
569 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
570 AssertReturn(off + cbRead <= pVol->cbVolume, VERR_INVALID_PARAMETER);
571
572 return rtDvmDiskRead(pVol->pVolMgr->pDisk, pVol->offStart + off, pvBuf, cbRead);
573}
574
575static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeWrite(RTDVMVOLUMEFMT hVolFmt, uint64_t off, const void *pvBuf, size_t cbWrite)
576{
577 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
578 AssertReturn(off + cbWrite <= pVol->cbVolume, VERR_INVALID_PARAMETER);
579
580 return rtDvmDiskWrite(pVol->pVolMgr->pDisk, pVol->offStart + off, pvBuf, cbWrite);
581}
582
583DECL_HIDDEN_CONST(const RTDVMFMTOPS) g_rtDvmFmtBsdLbl =
584{
585 /* pcszFmt */
586 "BsdLabel",
587 /* enmFormat, */
588 RTDVMFORMATTYPE_BSD_LABEL,
589 /* pfnProbe */
590 rtDvmFmtBsdLblProbe,
591 /* pfnOpen */
592 rtDvmFmtBsdLblOpen,
593 /* pfnInitialize */
594 rtDvmFmtBsdLblInitialize,
595 /* pfnClose */
596 rtDvmFmtBsdLblClose,
597 /* pfnQueryRangeUse */
598 rtDvmFmtBsdLblQueryRangeUse,
599 /* pfnQueryDiskUuid */
600 NULL,
601 /* pfnGetValidVolumes */
602 rtDvmFmtBsdLblGetValidVolumes,
603 /* pfnGetMaxVolumes */
604 rtDvmFmtBsdLblGetMaxVolumes,
605 /* pfnQueryFirstVolume */
606 rtDvmFmtBsdLblQueryFirstVolume,
607 /* pfnQueryNextVolume */
608 rtDvmFmtBsdLblQueryNextVolume,
609 /* pfnVolumeClose */
610 rtDvmFmtBsdLblVolumeClose,
611 /* pfnVolumeGetSize */
612 rtDvmFmtBsdLblVolumeGetSize,
613 /* pfnVolumeQueryName */
614 rtDvmFmtBsdLblVolumeQueryName,
615 /* pfnVolumeGetType */
616 rtDvmFmtBsdLblVolumeGetType,
617 /* pfnVolumeGetFlags */
618 rtDvmFmtBsdLblVolumeGetFlags,
619 /* pfnVolumeQueryRange */
620 rtDvmFmtBsdLblVolumeQueryRange,
621 /* pfnVolumeIsRangeIntersecting */
622 rtDvmFmtBsdLblVolumeIsRangeIntersecting,
623 /* pfnVolumeQueryTableLocation */
624 rtDvmFmtBsdLblVolumeQueryTableLocation,
625 /* pfnVolumeGetIndex */
626 rtDvmFmtBsdLblVolumeGetIndex,
627 /* pfnVolumeQueryProp */
628 rtDvmFmtBsdLblVolumeQueryProp,
629 /* pfnVolumeRead */
630 rtDvmFmtBsdLblVolumeRead,
631 /* pfnVolumeWrite */
632 rtDvmFmtBsdLblVolumeWrite
633};
634
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette