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  }