github.com/Microsoft/azure-vhd-utils@v0.0.0-20230613175315-7c30a3748a1b/vhdcore/block/sectorFactory.go (about) 1 package block 2 3 import ( 4 "fmt" 5 6 "github.com/Microsoft/azure-vhd-utils/vhdcore" 7 "github.com/Microsoft/azure-vhd-utils/vhdcore/reader" 8 ) 9 10 // SectorFactory type is used to create Sector instance by reading 512 byte sector from block's 'data section'. 11 // 12 type SectorFactory struct { 13 vhdReader *reader.VhdReader 14 blockHasData func(uint32) bool 15 getBlockAddress func(uint32) int64 16 emptySectorBuf []byte 17 } 18 19 // NewSectorFactory creates a new instance of SectorFactory, which can be used to create Sector instances 20 // by reading 512 byte sector from block's 'data section' 21 // vhdReader is the reader to be used to read the sector, blockHasData is a function which can be used to 22 // check a block is empty by providing block identifier, getBlockAddress is a function which can be used 23 // to fetch the absolute byte offset of a block by providing block identifier. 24 // 25 func NewSectorFactory(vhdReader *reader.VhdReader, blockHasData func(uint32) bool, getBlockAddress func(uint32) int64) *SectorFactory { 26 return &SectorFactory{ 27 vhdReader: vhdReader, 28 blockHasData: blockHasData, 29 getBlockAddress: getBlockAddress, 30 } 31 } 32 33 // Create creates an instance of Sector by reading a 512 byte sector from the 'data section' of a block. 34 // block describes the block containing the sector, sectorIndex identifies the sector to read. 35 // This function return error if requested sector is invalid or in case of any read error. 36 // 37 func (f *SectorFactory) Create(block *Block, sectorIndex uint32) (*Sector, error) { 38 if int64(sectorIndex) > block.GetSectorCount() { 39 return nil, fmt.Errorf("Total sectors: %d, Requested Sectors: %d", block.GetSectorCount(), sectorIndex) 40 } 41 42 blockIndex := block.BlockIndex 43 if !f.blockHasData(blockIndex) { 44 return f.CreateEmptySector(blockIndex, sectorIndex), nil 45 } 46 47 blockDataSectionByteOffset := f.getBlockAddress(blockIndex) 48 sectorByteOffset := blockDataSectionByteOffset + vhdcore.VhdSectorLength*int64(sectorIndex) 49 sectorBuf := make([]byte, vhdcore.VhdSectorLength) 50 if _, err := f.vhdReader.ReadBytes(sectorByteOffset, sectorBuf); err != nil { 51 return nil, NewSectorReadError(blockIndex, sectorIndex, err) 52 } 53 54 return &Sector{ 55 BlockIndex: blockIndex, 56 SectorIndex: int64(sectorIndex), 57 Data: sectorBuf, 58 }, nil 59 } 60 61 // CreateEmptySector creates an instance of Sector representing empty sector. The Data property of this sector 62 // will be a slice of 512 bytes filled with zeros. 63 // 64 func (f *SectorFactory) CreateEmptySector(blockIndex, sectorIndex uint32) *Sector { 65 if f.emptySectorBuf == nil { 66 f.emptySectorBuf = make([]byte, vhdcore.VhdSectorLength) 67 } 68 69 return &Sector{ 70 BlockIndex: blockIndex, 71 SectorIndex: int64(sectorIndex), 72 Data: f.emptySectorBuf, 73 } 74 }