github.com/Microsoft/azure-vhd-utils@v0.0.0-20230613175315-7c30a3748a1b/vhdcore/header/parentlocator/factory.go (about) 1 package parentlocator 2 3 import ( 4 "fmt" 5 "github.com/Microsoft/azure-vhd-utils/vhdcore/reader" 6 ) 7 8 // Factory type is used to create ParentLocator instance by reading one entry 9 // in vhd header's parent-hard-disk-locator-info collection section. 10 // 11 type Factory struct { 12 vhdReader *reader.VhdReader 13 locatorOffset int64 14 } 15 16 // NewFactory creates a new instance of Factory, which can be used to create ParentLocator instance 17 // by reading one entry from the vhd header's parent-hard-disk-locator-info collection, 18 // locatorOffset is the offset of the entry to read, vhdReader is the reader to be used to read the entry. 19 // 20 func NewFactory(vhdReader *reader.VhdReader, locatorOffset int64) *Factory { 21 return &Factory{vhdReader: vhdReader, locatorOffset: locatorOffset} 22 } 23 24 // Create creates a ParentLocator instance by reading one entry in vhd header's parent-hard-disk-locator-info 25 // collection section of the disk. This function return error if any error occurs while reading or parsing 26 // the parent locators table fields. 27 // 28 func (f *Factory) Create() (*ParentLocator, error) { 29 locator := &ParentLocator{} 30 var err error 31 errDone := func() (*ParentLocator, error) { 32 return nil, err 33 } 34 35 locator.PlatformCode, err = f.readPlatformCode() 36 if err != nil { 37 return errDone() 38 } 39 40 locator.PlatformDataSpace, err = f.readPlatformDataSpace() 41 if err != nil { 42 return errDone() 43 } 44 45 locator.PlatformDataLength, err = f.readPlatformDataLength() 46 if err != nil { 47 return errDone() 48 } 49 50 locator.Reserved, err = f.readReserved() 51 if err != nil { 52 return errDone() 53 } 54 55 locator.PlatformDataOffset, err = f.readPlatformDataOffset() 56 if err != nil { 57 return errDone() 58 } 59 60 fileLocator := make([]byte, locator.PlatformDataLength) 61 _, err = f.vhdReader.ReadBytes(locator.PlatformDataOffset, fileLocator) 62 if err != nil { 63 err = NewParseError("ParentLocator", fmt.Errorf("Unable to resolve file locator: %v", err)) 64 return errDone() 65 } 66 67 locator.SetPlatformSpecificFileLocator(fileLocator) 68 return locator, nil 69 } 70 71 // readPlatformCode reads the field that stores the platform-specific format used to encode the 72 // file locator in parent-hard-disk-locator-info 73 // This function return error if no or fewer bytes could be read. The value is stored as 4 byte 74 // value starting at offset 0 relative to the beginning of this parent-hard-disk-locator. This value 75 // is stored in big-endian format. 76 // 77 func (f *Factory) readPlatformCode() (PlatformCode, error) { 78 value, err := f.vhdReader.ReadInt32(f.locatorOffset + 0) 79 if err != nil { 80 return PlatformCodeNone, NewParseError("PlatformCode", err) 81 } 82 return PlatformCode(value), nil 83 } 84 85 // readPlatformDataSpace reads the field that stores the number of 512-byte sectors needed to store 86 // the parent hard disk file locator. This function return error if no or fewer bytes could be read. 87 // The value is stored as 4 byte value starting at offset 4 relative to the beginning parent-hard-disk-locator-info. 88 // This value is stored in big-endian format. 89 // 90 func (f *Factory) readPlatformDataSpace() (int32, error) { 91 value, err := f.vhdReader.ReadInt32(f.locatorOffset + 4) 92 if err != nil { 93 return -1, NewParseError("PlatformDataSpace", err) 94 } 95 return value, nil 96 } 97 98 // readPlatformDataLength reads the field that stores the actual length of the parent hard disk 99 // locator in bytes. This function return error if no or fewer bytes could be read. The value is stored 100 // as 4 byte value starting at offset 8 relative to the beginning parent-hard-disk-locator-info. This value 101 // is stored in big-endian format. 102 // 103 func (f *Factory) readPlatformDataLength() (int32, error) { 104 value, err := f.vhdReader.ReadInt32(f.locatorOffset + 8) 105 if err != nil { 106 return -1, NewParseError("PlatformDataLength", err) 107 } 108 return value, nil 109 } 110 111 // readReserved reads the reserved field value which is currently set to 0. 112 // This function return error if no or fewer bytes could be read. The value is stored as 4 byte 113 // value starting at offset 12 relative to the beginning parent-hard-disk-locator-info. 114 // This value is stored in big-endian format. 115 // 116 func (f *Factory) readReserved() (int32, error) { 117 value, err := f.vhdReader.ReadInt32(f.locatorOffset + 12) 118 if err != nil { 119 return -1, NewParseError("Reserved", err) 120 } 121 return value, nil 122 } 123 124 // readPlatformDataOffset reads the field that stores the absolute file offset in bytes where the platform 125 // specific file locator data is stored. Call to this function is panic if no or fewer bytes could be read. 126 // The value is stored as 4 byte value starting at offset 16 relative to the beginning parent-hard-disk-locator-info. 127 // This value is stored in big-endian format. 128 // 129 func (f *Factory) readPlatformDataOffset() (int64, error) { 130 value, err := f.vhdReader.ReadInt64(f.locatorOffset + 16) 131 if err != nil { 132 return -1, NewParseError("PlatformDataOffset", err) 133 } 134 return value, nil 135 }