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  }