github.com/Microsoft/azure-vhd-utils@v0.0.0-20230613175315-7c30a3748a1b/vhdcore/writer/vhdWriter.go (about) 1 package writer 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "io" 7 "time" 8 "unsafe" 9 10 "github.com/Microsoft/azure-vhd-utils/vhdcore" 11 ) 12 13 // VhdWriter is the writer used by various components responsible for writing header and 14 // footer of the VHD. 15 // 16 type VhdWriter struct { 17 *BinaryWriter 18 } 19 20 // NewVhdWriter creates new instance of the VhdWriter, that writes to the underlying target, 21 // size is the size of the target in bytes. 22 // 23 func NewVhdWriter(target io.WriterAt, size int64) *VhdWriter { 24 var order binary.ByteOrder 25 if isLittleEndian() { 26 order = binary.BigEndian 27 } else { 28 order = binary.LittleEndian 29 } 30 return &VhdWriter{NewBinaryWriter(target, order, size)} 31 } 32 33 // NewVhdWriterFromByteSlice creates a new instance of VhdWriter, that uses the given byte 34 // slice as the underlying target to write to. 35 // 36 func NewVhdWriterFromByteSlice(b []byte) *VhdWriter { 37 return NewVhdWriter(ByteSliceWriteAt(b), int64(len(b))) 38 } 39 40 // WriteTimeStamp writes vhd timestamp represented by the given time to underlying source 41 // starting at byte offset off. 42 // 43 func (r *VhdWriter) WriteTimeStamp(off int64, time *time.Time) { 44 vhdTimeStamp := vhdcore.NewVhdTimeStamp(time) 45 r.WriteUInt32(off, vhdTimeStamp.TotalSeconds) 46 } 47 48 // ByteSliceWriteAt is a type that satisfies io.WriteAt interface for byte slice. 49 // 50 type ByteSliceWriteAt []byte 51 52 // WriteAt copies len(b) bytes to the byte slice starting at byte offset off. It returns the number 53 // of bytes copied and an error, if any. WriteAt returns a non-nil error when n != len(b). 54 // 55 func (s ByteSliceWriteAt) WriteAt(b []byte, off int64) (n int, err error) { 56 if off < 0 || off > int64(len(s)) { 57 err = fmt.Errorf("Index %d is out of the boundary %d", off, len(s)-1) 58 return 59 } 60 61 n = copy(s[off:], b) 62 if n != len(b) { 63 err = fmt.Errorf("Could write only %d bytes, as source is %d bytes and destination is %d bytes", n, len(b), len(s)) 64 } 65 66 return 67 } 68 69 // isLittleEndian returns true if the host machine is little endian, false for big endian. 70 // 71 func isLittleEndian() bool { 72 var i int32 = 0x01020304 73 u := unsafe.Pointer(&i) 74 pb := (*byte)(u) 75 b := *pb 76 return (b == 0x04) 77 }