mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Revendor Microsoft/go-winio @ v0.4.5
Signed-off-by: John Howard <jhoward@microsoft.com>
This commit is contained in:
parent
187cd25517
commit
779469d9c9
6 changed files with 249 additions and 8 deletions
|
@ -1,7 +1,7 @@
|
||||||
# the following lines are in sorted order, FYI
|
# the following lines are in sorted order, FYI
|
||||||
github.com/Azure/go-ansiterm 19f72df4d05d31cbe1c56bfc8045c96babff6c7e
|
github.com/Azure/go-ansiterm 19f72df4d05d31cbe1c56bfc8045c96babff6c7e
|
||||||
github.com/Microsoft/hcsshim v0.6.3
|
github.com/Microsoft/hcsshim v0.6.3
|
||||||
github.com/Microsoft/go-winio v0.4.4
|
github.com/Microsoft/go-winio v0.4.5
|
||||||
github.com/moby/buildkit da2b9dc7dab99e824b2b1067ad7d0523e32dd2d9 https://github.com/dmcgowan/buildkit.git
|
github.com/moby/buildkit da2b9dc7dab99e824b2b1067ad7d0523e32dd2d9 https://github.com/dmcgowan/buildkit.git
|
||||||
github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76
|
github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76
|
||||||
github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
|
github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
|
||||||
|
|
14
vendor/github.com/Microsoft/go-winio/backup.go
generated
vendored
14
vendor/github.com/Microsoft/go-winio/backup.go
generated
vendored
|
@ -68,10 +68,20 @@ func NewBackupStreamReader(r io.Reader) *BackupStreamReader {
|
||||||
return &BackupStreamReader{r, 0}
|
return &BackupStreamReader{r, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next backup stream and prepares for calls to Write(). It skips the remainder of the current stream if
|
// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if
|
||||||
// it was not completely read.
|
// it was not completely read.
|
||||||
func (r *BackupStreamReader) Next() (*BackupHeader, error) {
|
func (r *BackupStreamReader) Next() (*BackupHeader, error) {
|
||||||
if r.bytesLeft > 0 {
|
if r.bytesLeft > 0 {
|
||||||
|
if s, ok := r.r.(io.Seeker); ok {
|
||||||
|
// Make sure Seek on io.SeekCurrent sometimes succeeds
|
||||||
|
// before trying the actual seek.
|
||||||
|
if _, err := s.Seek(0, io.SeekCurrent); err == nil {
|
||||||
|
if _, err = s.Seek(r.bytesLeft, io.SeekCurrent); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r.bytesLeft = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
if _, err := io.Copy(ioutil.Discard, r); err != nil {
|
if _, err := io.Copy(ioutil.Discard, r); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -220,7 +230,7 @@ type BackupFileWriter struct {
|
||||||
ctx uintptr
|
ctx uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBackupFileWrtier returns a new BackupFileWriter from a file handle. If includeSecurity is true,
|
// NewBackupFileWriter returns a new BackupFileWriter from a file handle. If includeSecurity is true,
|
||||||
// Write() will attempt to restore the security descriptor from the stream.
|
// Write() will attempt to restore the security descriptor from the stream.
|
||||||
func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter {
|
func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter {
|
||||||
w := &BackupFileWriter{f, includeSecurity, 0}
|
w := &BackupFileWriter{f, includeSecurity, 0}
|
||||||
|
|
92
vendor/github.com/Microsoft/go-winio/backuptar/tar.go
generated
vendored
92
vendor/github.com/Microsoft/go-winio/backuptar/tar.go
generated
vendored
|
@ -36,6 +36,7 @@ const (
|
||||||
hdrSecurityDescriptor = "sd"
|
hdrSecurityDescriptor = "sd"
|
||||||
hdrRawSecurityDescriptor = "rawsd"
|
hdrRawSecurityDescriptor = "rawsd"
|
||||||
hdrMountPoint = "mountpoint"
|
hdrMountPoint = "mountpoint"
|
||||||
|
hdrEaPrefix = "xattr."
|
||||||
)
|
)
|
||||||
|
|
||||||
func writeZeroes(w io.Writer, count int64) error {
|
func writeZeroes(w io.Writer, count int64) error {
|
||||||
|
@ -118,6 +119,21 @@ func BasicInfoHeader(name string, size int64, fileInfo *winio.FileBasicInfo) *ta
|
||||||
func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size int64, fileInfo *winio.FileBasicInfo) error {
|
func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size int64, fileInfo *winio.FileBasicInfo) error {
|
||||||
name = filepath.ToSlash(name)
|
name = filepath.ToSlash(name)
|
||||||
hdr := BasicInfoHeader(name, size, fileInfo)
|
hdr := BasicInfoHeader(name, size, fileInfo)
|
||||||
|
|
||||||
|
// If r can be seeked, then this function is two-pass: pass 1 collects the
|
||||||
|
// tar header data, and pass 2 copies the data stream. If r cannot be
|
||||||
|
// seeked, then some header data (in particular EAs) will be silently lost.
|
||||||
|
var (
|
||||||
|
restartPos int64
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
sr, readTwice := r.(io.Seeker)
|
||||||
|
if readTwice {
|
||||||
|
if restartPos, err = sr.Seek(0, io.SeekCurrent); err != nil {
|
||||||
|
readTwice = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
br := winio.NewBackupStreamReader(r)
|
br := winio.NewBackupStreamReader(r)
|
||||||
var dataHdr *winio.BackupHeader
|
var dataHdr *winio.BackupHeader
|
||||||
for dataHdr == nil {
|
for dataHdr == nil {
|
||||||
|
@ -131,7 +147,9 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
|
||||||
switch bhdr.Id {
|
switch bhdr.Id {
|
||||||
case winio.BackupData:
|
case winio.BackupData:
|
||||||
hdr.Mode |= c_ISREG
|
hdr.Mode |= c_ISREG
|
||||||
dataHdr = bhdr
|
if !readTwice {
|
||||||
|
dataHdr = bhdr
|
||||||
|
}
|
||||||
case winio.BackupSecurity:
|
case winio.BackupSecurity:
|
||||||
sd, err := ioutil.ReadAll(br)
|
sd, err := ioutil.ReadAll(br)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -151,18 +169,54 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size
|
||||||
hdr.Winheaders[hdrMountPoint] = "1"
|
hdr.Winheaders[hdrMountPoint] = "1"
|
||||||
}
|
}
|
||||||
hdr.Linkname = rp.Target
|
hdr.Linkname = rp.Target
|
||||||
case winio.BackupEaData, winio.BackupLink, winio.BackupPropertyData, winio.BackupObjectId, winio.BackupTxfsData:
|
|
||||||
|
case winio.BackupEaData:
|
||||||
|
eab, err := ioutil.ReadAll(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
eas, err := winio.DecodeExtendedAttributes(eab)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, ea := range eas {
|
||||||
|
// Use base64 encoding for the binary value. Note that there
|
||||||
|
// is no way to encode the EA's flags, since their use doesn't
|
||||||
|
// make any sense for persisted EAs.
|
||||||
|
hdr.Winheaders[hdrEaPrefix+ea.Name] = base64.StdEncoding.EncodeToString(ea.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
case winio.BackupAlternateData, winio.BackupLink, winio.BackupPropertyData, winio.BackupObjectId, winio.BackupTxfsData:
|
||||||
// ignore these streams
|
// ignore these streams
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("%s: unknown stream ID %d", name, bhdr.Id)
|
return fmt.Errorf("%s: unknown stream ID %d", name, bhdr.Id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := t.WriteHeader(hdr)
|
err = t.WriteHeader(hdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if readTwice {
|
||||||
|
// Get back to the data stream.
|
||||||
|
if _, err = sr.Seek(restartPos, io.SeekStart); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for dataHdr == nil {
|
||||||
|
bhdr, err := br.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if bhdr.Id == winio.BackupData {
|
||||||
|
dataHdr = bhdr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if dataHdr != nil {
|
if dataHdr != nil {
|
||||||
// A data stream was found. Copy the data.
|
// A data stream was found. Copy the data.
|
||||||
if (dataHdr.Attributes & winio.StreamSparseAttributes) == 0 {
|
if (dataHdr.Attributes & winio.StreamSparseAttributes) == 0 {
|
||||||
|
@ -293,6 +347,38 @@ func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var eas []winio.ExtendedAttribute
|
||||||
|
for k, v := range hdr.Winheaders {
|
||||||
|
if !strings.HasPrefix(k, hdrEaPrefix) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
data, err := base64.StdEncoding.DecodeString(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
eas = append(eas, winio.ExtendedAttribute{
|
||||||
|
Name: k[len(hdrEaPrefix):],
|
||||||
|
Value: data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(eas) != 0 {
|
||||||
|
eadata, err := winio.EncodeExtendedAttributes(eas)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bhdr := winio.BackupHeader{
|
||||||
|
Id: winio.BackupEaData,
|
||||||
|
Size: int64(len(eadata)),
|
||||||
|
}
|
||||||
|
err = bw.WriteHeader(&bhdr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = bw.Write(eadata)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
if hdr.Typeflag == tar.TypeSymlink {
|
if hdr.Typeflag == tar.TypeSymlink {
|
||||||
_, isMountPoint := hdr.Winheaders[hdrMountPoint]
|
_, isMountPoint := hdr.Winheaders[hdrMountPoint]
|
||||||
rp := winio.ReparsePoint{
|
rp := winio.ReparsePoint{
|
||||||
|
|
137
vendor/github.com/Microsoft/go-winio/ea.go
generated
vendored
Normal file
137
vendor/github.com/Microsoft/go-winio/ea.go
generated
vendored
Normal file
|
@ -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
|
||||||
|
}
|
8
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
8
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
|
@ -78,6 +78,7 @@ func initIo() {
|
||||||
type win32File struct {
|
type win32File struct {
|
||||||
handle syscall.Handle
|
handle syscall.Handle
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
wgLock sync.RWMutex
|
||||||
closing atomicBool
|
closing atomicBool
|
||||||
readDeadline deadlineHandler
|
readDeadline deadlineHandler
|
||||||
writeDeadline deadlineHandler
|
writeDeadline deadlineHandler
|
||||||
|
@ -114,14 +115,18 @@ func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
|
||||||
|
|
||||||
// closeHandle closes the resources associated with a Win32 handle
|
// closeHandle closes the resources associated with a Win32 handle
|
||||||
func (f *win32File) closeHandle() {
|
func (f *win32File) closeHandle() {
|
||||||
|
f.wgLock.Lock()
|
||||||
// Atomically set that we are closing, releasing the resources only once.
|
// Atomically set that we are closing, releasing the resources only once.
|
||||||
if !f.closing.swap(true) {
|
if !f.closing.swap(true) {
|
||||||
|
f.wgLock.Unlock()
|
||||||
// cancel all IO and wait for it to complete
|
// cancel all IO and wait for it to complete
|
||||||
cancelIoEx(f.handle, nil)
|
cancelIoEx(f.handle, nil)
|
||||||
f.wg.Wait()
|
f.wg.Wait()
|
||||||
// at this point, no new IO can start
|
// at this point, no new IO can start
|
||||||
syscall.Close(f.handle)
|
syscall.Close(f.handle)
|
||||||
f.handle = 0
|
f.handle = 0
|
||||||
|
} else {
|
||||||
|
f.wgLock.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,10 +139,13 @@ func (f *win32File) Close() error {
|
||||||
// prepareIo prepares for a new IO operation.
|
// prepareIo prepares for a new IO operation.
|
||||||
// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
|
// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
|
||||||
func (f *win32File) prepareIo() (*ioOperation, error) {
|
func (f *win32File) prepareIo() (*ioOperation, error) {
|
||||||
|
f.wgLock.RLock()
|
||||||
if f.closing.isSet() {
|
if f.closing.isSet() {
|
||||||
|
f.wgLock.RUnlock()
|
||||||
return nil, ErrFileClosed
|
return nil, ErrFileClosed
|
||||||
}
|
}
|
||||||
f.wg.Add(1)
|
f.wg.Add(1)
|
||||||
|
f.wgLock.RUnlock()
|
||||||
c := &ioOperation{}
|
c := &ioOperation{}
|
||||||
c.ch = make(chan ioResult)
|
c.ch = make(chan ioResult)
|
||||||
return c, nil
|
return c, nil
|
||||||
|
|
4
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
4
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
|
@ -265,9 +265,9 @@ func (l *win32PipeListener) listenerRoutine() {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Wait for the client to connect.
|
// Wait for the client to connect.
|
||||||
ch := make(chan error)
|
ch := make(chan error)
|
||||||
go func() {
|
go func(p *win32File) {
|
||||||
ch <- connectPipe(p)
|
ch <- connectPipe(p)
|
||||||
}()
|
}(p)
|
||||||
select {
|
select {
|
||||||
case err = <-ch:
|
case err = <-ch:
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue