github.com/Microsoft/azure-vhd-utils@v0.0.0-20230613175315-7c30a3748a1b/vhdcore/vhdfile/vhdFile.go (about) 1 package vhdfile 2 3 import ( 4 "fmt" 5 6 "github.com/Microsoft/azure-vhd-utils/vhdcore/bat" 7 "github.com/Microsoft/azure-vhd-utils/vhdcore/block" 8 "github.com/Microsoft/azure-vhd-utils/vhdcore/footer" 9 "github.com/Microsoft/azure-vhd-utils/vhdcore/header" 10 "github.com/Microsoft/azure-vhd-utils/vhdcore/reader" 11 ) 12 13 // VhdFile represents a VHD. 14 // 15 type VhdFile struct { 16 // Footer represents the disk's footer. 17 Footer *footer.Footer 18 // Header represents the disk's header, this field is nil for fixed VHD. 19 // Only Dynamic and Differencing disk has header.make 20 21 Header *header.Header 22 // BlockAllocationTable represents the table holding absolute offset to the first sector 23 // of blocks in the disk. Only Dynamic and Differencing disk has BAT. 24 BlockAllocationTable *bat.BlockAllocationTable 25 // VhdReader is the reader that can be used to read the disk. 26 VhdReader *reader.VhdReader 27 // Parent represents the parent VHD of Differencing disk, this field is nil for fixed 28 // and dynamic disk. 29 Parent *VhdFile 30 } 31 32 // GetDiskType returns the type of the disk. Possible values are DiskTypeFixed, DiskTypeDynamic 33 // and DiskTypeDifferencing. 34 // 35 func (f *VhdFile) GetDiskType() footer.DiskType { 36 return f.Footer.DiskType 37 } 38 39 // GetBlockFactory returns a BlockFactory instance that can be used to create Block instances 40 // that represents blocks in the disk. 41 // 42 func (f *VhdFile) GetBlockFactory() (block.Factory, error) { 43 params := &block.FactoryParams{ 44 VhdHeader: f.Header, 45 VhdFooter: f.Footer, 46 VhdReader: f.VhdReader, 47 } 48 49 switch f.GetDiskType() { 50 case footer.DiskTypeFixed: 51 return block.NewFixedDiskBlockFactoryWithDefaultBlockSize(params), nil 52 53 case footer.DiskTypeDynamic: 54 params.BlockAllocationTable = f.BlockAllocationTable 55 return block.NewDynamicDiskFactory(params), nil 56 57 case footer.DiskTypeDifferencing: 58 params.BlockAllocationTable = f.BlockAllocationTable 59 parentVhdFile := f.Parent 60 if parentVhdFile.GetDiskType() == footer.DiskTypeFixed { 61 params.ParentBlockFactory = block.NewFixedDiskBlockFactory( 62 &block.FactoryParams{ 63 VhdHeader: parentVhdFile.Header, 64 VhdFooter: parentVhdFile.Footer, 65 VhdReader: parentVhdFile.VhdReader, 66 }, 67 int64(f.Header.BlockSize)) // The block-size of parent FixedDisk and this DifferentialDisk will be same. 68 69 } else { 70 var err error 71 params.ParentBlockFactory, err = parentVhdFile.GetBlockFactory() 72 if err != nil { 73 return nil, err 74 } 75 } 76 return block.NewDifferencingDiskBlockFactory(params), nil 77 } 78 79 return nil, fmt.Errorf("Unsupported disk format: %d", f.GetDiskType()) 80 } 81 82 // GetIdentityChain returns VHD identity chain, for differencing disk this will be a slice with 83 // unique ids of this and all it's ancestor disks. For fixed and dynamic disk, this will be a 84 // slice with one entry representing disk's unique id. 85 // 86 func (f *VhdFile) GetIdentityChain() []string { 87 ids := []string{f.Footer.UniqueID.String()} 88 for p := f.Parent; p != nil; p = p.Parent { 89 ids = append(ids, p.Footer.UniqueID.String()) 90 } 91 92 return ids 93 }