github.com/Microsoft/azure-vhd-utils@v0.0.0-20230613175315-7c30a3748a1b/vhdcore/block/differencingDiskBlockReader.go (about) 1 package block 2 3 import ( 4 "github.com/Microsoft/azure-vhd-utils/vhdcore/bat" 5 "github.com/Microsoft/azure-vhd-utils/vhdcore/footer" 6 "github.com/Microsoft/azure-vhd-utils/vhdcore/reader" 7 ) 8 9 // DifferencingDiskBlockReader type satisfies BlockDataReader interface, 10 // implementation of BlockDataReader::Read by this type can read the 'data' section 11 // of a differencing disk's block. 12 // 13 type DifferencingDiskBlockReader struct { 14 vhdReader *reader.VhdReader 15 blockAllocationTable *bat.BlockAllocationTable 16 blockSizeInBytes uint32 17 emptyBlockData []byte 18 } 19 20 // NewDifferencingDiskBlockReader create a new instance of DifferencingDiskBlockReader which read 21 // the 'data' section of differencing disk block. 22 // The parameter vhdReader is the reader to read the disk 23 // The parameter blockAllocationTable represents the disk's BAT 24 // The parameter blockSizeInBytes is the size of the differencing disk block 25 // 26 func NewDifferencingDiskBlockReader(vhdReader *reader.VhdReader, blockAllocationTable *bat.BlockAllocationTable, blockSizeInBytes uint32) *DifferencingDiskBlockReader { 27 return &DifferencingDiskBlockReader{ 28 vhdReader: vhdReader, 29 blockAllocationTable: blockAllocationTable, 30 blockSizeInBytes: blockSizeInBytes, 31 emptyBlockData: nil, 32 } 33 } 34 35 // Read reads the data in a block of a differencing disk 36 // The parameter block represents the block whose 'data' section to read 37 // 38 func (r *DifferencingDiskBlockReader) Read(block *Block) ([]byte, error) { 39 blockIndex := block.BlockIndex 40 if !r.blockAllocationTable.HasData(blockIndex) { 41 if r.emptyBlockData == nil { 42 r.emptyBlockData = make([]byte, r.blockSizeInBytes) 43 } 44 return r.emptyBlockData, nil 45 } 46 47 blockDataBuffer := make([]byte, r.blockSizeInBytes) 48 index := 0 49 sectorCount := block.GetSectorCount() 50 for i := int64(0); i < sectorCount; i++ { 51 sector, err := block.GetSector(uint32(i)) 52 if err != nil { 53 return nil, NewDataReadError(blockIndex, footer.DiskTypeDifferencing, err) 54 } 55 56 n := copy(blockDataBuffer[index:], sector.Data) 57 index += n 58 } 59 60 return blockDataBuffer, nil 61 }