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  }