VOL-381 add unum container to support ONOS cluster formation under swarm

Change-Id: Ic260edda19bb199ed040f05164ab605f28c919d0
diff --git a/unum/vendor/github.com/Microsoft/go-winio/ea.go b/unum/vendor/github.com/Microsoft/go-winio/ea.go
new file mode 100644
index 0000000..b37e930
--- /dev/null
+++ b/unum/vendor/github.com/Microsoft/go-winio/ea.go
@@ -0,0 +1,137 @@
+package winio

+

+import (

+	"bytes"

+	"encoding/binary"

+	"errors"

+)

+

+type fileFullEaInformation struct {

+	NextEntryOffset uint32

+	Flags           uint8

+	NameLength      uint8

+	ValueLength     uint16

+}

+

+var (

+	fileFullEaInformationSize = binary.Size(&fileFullEaInformation{})

+

+	errInvalidEaBuffer = errors.New("invalid extended attribute buffer")

+	errEaNameTooLarge  = errors.New("extended attribute name too large")

+	errEaValueTooLarge = errors.New("extended attribute value too large")

+)

+

+// ExtendedAttribute represents a single Windows EA.

+type ExtendedAttribute struct {

+	Name  string

+	Value []byte

+	Flags uint8

+}

+

+func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {

+	var info fileFullEaInformation

+	err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)

+	if err != nil {

+		err = errInvalidEaBuffer

+		return

+	}

+

+	nameOffset := fileFullEaInformationSize

+	nameLen := int(info.NameLength)

+	valueOffset := nameOffset + int(info.NameLength) + 1

+	valueLen := int(info.ValueLength)

+	nextOffset := int(info.NextEntryOffset)

+	if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {

+		err = errInvalidEaBuffer

+		return

+	}

+

+	ea.Name = string(b[nameOffset : nameOffset+nameLen])

+	ea.Value = b[valueOffset : valueOffset+valueLen]

+	ea.Flags = info.Flags

+	if info.NextEntryOffset != 0 {

+		nb = b[info.NextEntryOffset:]

+	}

+	return

+}

+

+// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION

+// buffer retrieved from BackupRead, ZwQueryEaFile, etc.

+func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {

+	for len(b) != 0 {

+		ea, nb, err := parseEa(b)

+		if err != nil {

+			return nil, err

+		}

+

+		eas = append(eas, ea)

+		b = nb

+	}

+	return

+}

+

+func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {

+	if int(uint8(len(ea.Name))) != len(ea.Name) {

+		return errEaNameTooLarge

+	}

+	if int(uint16(len(ea.Value))) != len(ea.Value) {

+		return errEaValueTooLarge

+	}

+	entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value))

+	withPadding := (entrySize + 3) &^ 3

+	nextOffset := uint32(0)

+	if !last {

+		nextOffset = withPadding

+	}

+	info := fileFullEaInformation{

+		NextEntryOffset: nextOffset,

+		Flags:           ea.Flags,

+		NameLength:      uint8(len(ea.Name)),

+		ValueLength:     uint16(len(ea.Value)),

+	}

+

+	err := binary.Write(buf, binary.LittleEndian, &info)

+	if err != nil {

+		return err

+	}

+

+	_, err = buf.Write([]byte(ea.Name))

+	if err != nil {

+		return err

+	}

+

+	err = buf.WriteByte(0)

+	if err != nil {

+		return err

+	}

+

+	_, err = buf.Write(ea.Value)

+	if err != nil {

+		return err

+	}

+

+	_, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize])

+	if err != nil {

+		return err

+	}

+

+	return nil

+}

+

+// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION

+// buffer for use with BackupWrite, ZwSetEaFile, etc.

+func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) {

+	var buf bytes.Buffer

+	for i := range eas {

+		last := false

+		if i == len(eas)-1 {

+			last = true

+		}

+

+		err := writeEa(&buf, &eas[i], last)

+		if err != nil {

+			return nil, err

+		}

+	}

+	return buf.Bytes(), nil

+}