Update hcsshim tag to v0.10.0-rc.9
Signed-off-by: Kirtana Ashok <kiashok@microsoft.com>
This commit is contained in:
12
vendor/github.com/Microsoft/go-winio/.golangci.yml
generated
vendored
12
vendor/github.com/Microsoft/go-winio/.golangci.yml
generated
vendored
@@ -35,6 +35,18 @@ issues:
|
||||
text: "^line-length-limit: "
|
||||
source: "^//(go:generate|sys) "
|
||||
|
||||
#TODO: remove after upgrading to go1.18
|
||||
# ignore comment spacing for nolint and sys directives
|
||||
- linters:
|
||||
- revive
|
||||
text: "^comment-spacings: no space between comment delimiter and comment text"
|
||||
source: "//(cspell:|nolint:|sys |todo)"
|
||||
|
||||
# not on go 1.18 yet, so no any
|
||||
- linters:
|
||||
- revive
|
||||
text: "^use-any: since GO 1.18 'interface{}' can be replaced by 'any'"
|
||||
|
||||
# allow unjustified ignores of error checks in defer statements
|
||||
- linters:
|
||||
- nolintlint
|
||||
|
||||
6
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
6
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
@@ -23,7 +23,7 @@ import (
|
||||
const afHVSock = 34 // AF_HYPERV
|
||||
|
||||
// Well known Service and VM IDs
|
||||
//https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service#vmid-wildcards
|
||||
// https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service#vmid-wildcards
|
||||
|
||||
// HvsockGUIDWildcard is the wildcard VmId for accepting connections from all partitions.
|
||||
func HvsockGUIDWildcard() guid.GUID { // 00000000-0000-0000-0000-000000000000
|
||||
@@ -31,7 +31,7 @@ func HvsockGUIDWildcard() guid.GUID { // 00000000-0000-0000-0000-000000000000
|
||||
}
|
||||
|
||||
// HvsockGUIDBroadcast is the wildcard VmId for broadcasting sends to all partitions.
|
||||
func HvsockGUIDBroadcast() guid.GUID { //ffffffff-ffff-ffff-ffff-ffffffffffff
|
||||
func HvsockGUIDBroadcast() guid.GUID { // ffffffff-ffff-ffff-ffff-ffffffffffff
|
||||
return guid.GUID{
|
||||
Data1: 0xffffffff,
|
||||
Data2: 0xffff,
|
||||
@@ -246,7 +246,7 @@ func (l *HvsockListener) Accept() (_ net.Conn, err error) {
|
||||
var addrbuf [addrlen * 2]byte
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /*rxdatalen*/, addrlen, addrlen, &bytes, &c.o)
|
||||
err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /* rxdatalen */, addrlen, addrlen, &bytes, &c.o)
|
||||
if _, err = l.sock.asyncIO(c, nil, bytes, err); err != nil {
|
||||
return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
|
||||
}
|
||||
|
||||
2
vendor/github.com/Microsoft/go-winio/internal/fs/doc.go
generated
vendored
Normal file
2
vendor/github.com/Microsoft/go-winio/internal/fs/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// This package contains Win32 filesystem functionality.
|
||||
package fs
|
||||
202
vendor/github.com/Microsoft/go-winio/internal/fs/fs.go
generated
vendored
Normal file
202
vendor/github.com/Microsoft/go-winio/internal/fs/fs.go
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
//go:build windows
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/Microsoft/go-winio/internal/stringbuffer"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go fs.go
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
|
||||
//sys CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateFileW
|
||||
|
||||
const NullHandle windows.Handle = 0
|
||||
|
||||
// AccessMask defines standard, specific, and generic rights.
|
||||
//
|
||||
// Bitmask:
|
||||
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
// +---------------+---------------+-------------------------------+
|
||||
// |G|G|G|G|Resvd|A| StandardRights| SpecificRights |
|
||||
// |R|W|E|A| |S| | |
|
||||
// +-+-------------+---------------+-------------------------------+
|
||||
//
|
||||
// GR Generic Read
|
||||
// GW Generic Write
|
||||
// GE Generic Exectue
|
||||
// GA Generic All
|
||||
// Resvd Reserved
|
||||
// AS Access Security System
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/secauthz/access-mask
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants
|
||||
type AccessMask = windows.ACCESS_MASK
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const (
|
||||
// Not actually any.
|
||||
//
|
||||
// For CreateFile: "query certain metadata such as file, directory, or device attributes without accessing that file or device"
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew#parameters
|
||||
FILE_ANY_ACCESS AccessMask = 0
|
||||
|
||||
// Specific Object Access
|
||||
// from ntioapi.h
|
||||
|
||||
FILE_READ_DATA AccessMask = (0x0001) // file & pipe
|
||||
FILE_LIST_DIRECTORY AccessMask = (0x0001) // directory
|
||||
|
||||
FILE_WRITE_DATA AccessMask = (0x0002) // file & pipe
|
||||
FILE_ADD_FILE AccessMask = (0x0002) // directory
|
||||
|
||||
FILE_APPEND_DATA AccessMask = (0x0004) // file
|
||||
FILE_ADD_SUBDIRECTORY AccessMask = (0x0004) // directory
|
||||
FILE_CREATE_PIPE_INSTANCE AccessMask = (0x0004) // named pipe
|
||||
|
||||
FILE_READ_EA AccessMask = (0x0008) // file & directory
|
||||
FILE_READ_PROPERTIES AccessMask = FILE_READ_EA
|
||||
|
||||
FILE_WRITE_EA AccessMask = (0x0010) // file & directory
|
||||
FILE_WRITE_PROPERTIES AccessMask = FILE_WRITE_EA
|
||||
|
||||
FILE_EXECUTE AccessMask = (0x0020) // file
|
||||
FILE_TRAVERSE AccessMask = (0x0020) // directory
|
||||
|
||||
FILE_DELETE_CHILD AccessMask = (0x0040) // directory
|
||||
|
||||
FILE_READ_ATTRIBUTES AccessMask = (0x0080) // all
|
||||
|
||||
FILE_WRITE_ATTRIBUTES AccessMask = (0x0100) // all
|
||||
|
||||
FILE_ALL_ACCESS AccessMask = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF)
|
||||
FILE_GENERIC_READ AccessMask = (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE)
|
||||
FILE_GENERIC_WRITE AccessMask = (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE)
|
||||
FILE_GENERIC_EXECUTE AccessMask = (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE)
|
||||
|
||||
SPECIFIC_RIGHTS_ALL AccessMask = 0x0000FFFF
|
||||
|
||||
// Standard Access
|
||||
// from ntseapi.h
|
||||
|
||||
DELETE AccessMask = 0x0001_0000
|
||||
READ_CONTROL AccessMask = 0x0002_0000
|
||||
WRITE_DAC AccessMask = 0x0004_0000
|
||||
WRITE_OWNER AccessMask = 0x0008_0000
|
||||
SYNCHRONIZE AccessMask = 0x0010_0000
|
||||
|
||||
STANDARD_RIGHTS_REQUIRED AccessMask = 0x000F_0000
|
||||
|
||||
STANDARD_RIGHTS_READ AccessMask = READ_CONTROL
|
||||
STANDARD_RIGHTS_WRITE AccessMask = READ_CONTROL
|
||||
STANDARD_RIGHTS_EXECUTE AccessMask = READ_CONTROL
|
||||
|
||||
STANDARD_RIGHTS_ALL AccessMask = 0x001F_0000
|
||||
)
|
||||
|
||||
type FileShareMode uint32
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const (
|
||||
FILE_SHARE_NONE FileShareMode = 0x00
|
||||
FILE_SHARE_READ FileShareMode = 0x01
|
||||
FILE_SHARE_WRITE FileShareMode = 0x02
|
||||
FILE_SHARE_DELETE FileShareMode = 0x04
|
||||
FILE_SHARE_VALID_FLAGS FileShareMode = 0x07
|
||||
)
|
||||
|
||||
type FileCreationDisposition uint32
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const (
|
||||
// from winbase.h
|
||||
|
||||
CREATE_NEW FileCreationDisposition = 0x01
|
||||
CREATE_ALWAYS FileCreationDisposition = 0x02
|
||||
OPEN_EXISTING FileCreationDisposition = 0x03
|
||||
OPEN_ALWAYS FileCreationDisposition = 0x04
|
||||
TRUNCATE_EXISTING FileCreationDisposition = 0x05
|
||||
)
|
||||
|
||||
// CreateFile and co. take flags or attributes together as one parameter.
|
||||
// Define alias until we can use generics to allow both
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
|
||||
type FileFlagOrAttribute uint32
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const ( // from winnt.h
|
||||
FILE_FLAG_WRITE_THROUGH FileFlagOrAttribute = 0x8000_0000
|
||||
FILE_FLAG_OVERLAPPED FileFlagOrAttribute = 0x4000_0000
|
||||
FILE_FLAG_NO_BUFFERING FileFlagOrAttribute = 0x2000_0000
|
||||
FILE_FLAG_RANDOM_ACCESS FileFlagOrAttribute = 0x1000_0000
|
||||
FILE_FLAG_SEQUENTIAL_SCAN FileFlagOrAttribute = 0x0800_0000
|
||||
FILE_FLAG_DELETE_ON_CLOSE FileFlagOrAttribute = 0x0400_0000
|
||||
FILE_FLAG_BACKUP_SEMANTICS FileFlagOrAttribute = 0x0200_0000
|
||||
FILE_FLAG_POSIX_SEMANTICS FileFlagOrAttribute = 0x0100_0000
|
||||
FILE_FLAG_OPEN_REPARSE_POINT FileFlagOrAttribute = 0x0020_0000
|
||||
FILE_FLAG_OPEN_NO_RECALL FileFlagOrAttribute = 0x0010_0000
|
||||
FILE_FLAG_FIRST_PIPE_INSTANCE FileFlagOrAttribute = 0x0008_0000
|
||||
)
|
||||
|
||||
type FileSQSFlag = FileFlagOrAttribute
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const ( // from winbase.h
|
||||
SECURITY_ANONYMOUS FileSQSFlag = FileSQSFlag(SecurityAnonymous << 16)
|
||||
SECURITY_IDENTIFICATION FileSQSFlag = FileSQSFlag(SecurityIdentification << 16)
|
||||
SECURITY_IMPERSONATION FileSQSFlag = FileSQSFlag(SecurityImpersonation << 16)
|
||||
SECURITY_DELEGATION FileSQSFlag = FileSQSFlag(SecurityDelegation << 16)
|
||||
|
||||
SECURITY_SQOS_PRESENT FileSQSFlag = 0x00100000
|
||||
SECURITY_VALID_SQOS_FLAGS FileSQSFlag = 0x001F0000
|
||||
)
|
||||
|
||||
// GetFinalPathNameByHandle flags
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew#parameters
|
||||
type GetFinalPathFlag uint32
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const (
|
||||
GetFinalPathDefaultFlag GetFinalPathFlag = 0x0
|
||||
|
||||
FILE_NAME_NORMALIZED GetFinalPathFlag = 0x0
|
||||
FILE_NAME_OPENED GetFinalPathFlag = 0x8
|
||||
|
||||
VOLUME_NAME_DOS GetFinalPathFlag = 0x0
|
||||
VOLUME_NAME_GUID GetFinalPathFlag = 0x1
|
||||
VOLUME_NAME_NT GetFinalPathFlag = 0x2
|
||||
VOLUME_NAME_NONE GetFinalPathFlag = 0x4
|
||||
)
|
||||
|
||||
// getFinalPathNameByHandle facilitates calling the Windows API GetFinalPathNameByHandle
|
||||
// with the given handle and flags. It transparently takes care of creating a buffer of the
|
||||
// correct size for the call.
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
|
||||
func GetFinalPathNameByHandle(h windows.Handle, flags GetFinalPathFlag) (string, error) {
|
||||
b := stringbuffer.NewWString()
|
||||
//TODO: can loop infinitely if Win32 keeps returning the same (or a larger) n?
|
||||
for {
|
||||
n, err := windows.GetFinalPathNameByHandle(h, b.Pointer(), b.Cap(), uint32(flags))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// If the buffer wasn't large enough, n will be the total size needed (including null terminator).
|
||||
// Resize and try again.
|
||||
if n > b.Cap() {
|
||||
b.ResizeTo(n)
|
||||
continue
|
||||
}
|
||||
// If the buffer is large enough, n will be the size not including the null terminator.
|
||||
// Convert to a Go string and return.
|
||||
return b.String(), nil
|
||||
}
|
||||
}
|
||||
12
vendor/github.com/Microsoft/go-winio/internal/fs/security.go
generated
vendored
Normal file
12
vendor/github.com/Microsoft/go-winio/internal/fs/security.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
package fs
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level
|
||||
type SecurityImpersonationLevel int32 // C default enums underlying type is `int`, which is Go `int32`
|
||||
|
||||
// Impersonation levels
|
||||
const (
|
||||
SecurityAnonymous SecurityImpersonationLevel = 0
|
||||
SecurityIdentification SecurityImpersonationLevel = 1
|
||||
SecurityImpersonation SecurityImpersonationLevel = 2
|
||||
SecurityDelegation SecurityImpersonationLevel = 3
|
||||
)
|
||||
64
vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go
generated
vendored
Normal file
64
vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
//go:build windows
|
||||
|
||||
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
// Do the interface allocations only once for common
|
||||
// Errno values.
|
||||
const (
|
||||
errnoERROR_IO_PENDING = 997
|
||||
)
|
||||
|
||||
var (
|
||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||
errERROR_EINVAL error = syscall.EINVAL
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
// allocations at runtime.
|
||||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return errERROR_EINVAL
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
// TODO: add more here, after collecting data on the common
|
||||
// error values see on Windows. (perhaps when running
|
||||
// all.bat?)
|
||||
return e
|
||||
}
|
||||
|
||||
var (
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
)
|
||||
|
||||
func CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _CreateFile(_p0, access, mode, sa, createmode, attrs, templatefile)
|
||||
}
|
||||
|
||||
func _CreateFile(name *uint16, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
|
||||
handle = windows.Handle(r0)
|
||||
if handle == windows.InvalidHandle {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
4
vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
generated
vendored
4
vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
generated
vendored
@@ -100,8 +100,8 @@ func (f *runtimeFunc) Load() error {
|
||||
(*byte)(unsafe.Pointer(&f.addr)),
|
||||
uint32(unsafe.Sizeof(f.addr)),
|
||||
&n,
|
||||
nil, //overlapped
|
||||
0, //completionRoutine
|
||||
nil, // overlapped
|
||||
0, // completionRoutine
|
||||
)
|
||||
})
|
||||
return f.err
|
||||
|
||||
132
vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go
generated
vendored
Normal file
132
vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
package stringbuffer
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"unicode/utf16"
|
||||
)
|
||||
|
||||
// TODO: worth exporting and using in mkwinsyscall?
|
||||
|
||||
// Uint16BufferSize is the buffer size in the pool, chosen somewhat arbitrarily to accommodate
|
||||
// large path strings:
|
||||
// MAX_PATH (260) + size of volume GUID prefix (49) + null terminator = 310.
|
||||
const MinWStringCap = 310
|
||||
|
||||
// use *[]uint16 since []uint16 creates an extra allocation where the slice header
|
||||
// is copied to heap and then referenced via pointer in the interface header that sync.Pool
|
||||
// stores.
|
||||
var pathPool = sync.Pool{ // if go1.18+ adds Pool[T], use that to store []uint16 directly
|
||||
New: func() interface{} {
|
||||
b := make([]uint16, MinWStringCap)
|
||||
return &b
|
||||
},
|
||||
}
|
||||
|
||||
func newBuffer() []uint16 { return *(pathPool.Get().(*[]uint16)) }
|
||||
|
||||
// freeBuffer copies the slice header data, and puts a pointer to that in the pool.
|
||||
// This avoids taking a pointer to the slice header in WString, which can be set to nil.
|
||||
func freeBuffer(b []uint16) { pathPool.Put(&b) }
|
||||
|
||||
// WString is a wide string buffer ([]uint16) meant for storing UTF-16 encoded strings
|
||||
// for interacting with Win32 APIs.
|
||||
// Sizes are specified as uint32 and not int.
|
||||
//
|
||||
// It is not thread safe.
|
||||
type WString struct {
|
||||
// type-def allows casting to []uint16 directly, use struct to prevent that and allow adding fields in the future.
|
||||
|
||||
// raw buffer
|
||||
b []uint16
|
||||
}
|
||||
|
||||
// NewWString returns a [WString] allocated from a shared pool with an
|
||||
// initial capacity of at least [MinWStringCap].
|
||||
// Since the buffer may have been previously used, its contents are not guaranteed to be empty.
|
||||
//
|
||||
// The buffer should be freed via [WString.Free]
|
||||
func NewWString() *WString {
|
||||
return &WString{
|
||||
b: newBuffer(),
|
||||
}
|
||||
}
|
||||
|
||||
func (b *WString) Free() {
|
||||
if b.empty() {
|
||||
return
|
||||
}
|
||||
freeBuffer(b.b)
|
||||
b.b = nil
|
||||
}
|
||||
|
||||
// ResizeTo grows the buffer to at least c and returns the new capacity, freeing the
|
||||
// previous buffer back into pool.
|
||||
func (b *WString) ResizeTo(c uint32) uint32 {
|
||||
// allready sufficient (or n is 0)
|
||||
if c <= b.Cap() {
|
||||
return b.Cap()
|
||||
}
|
||||
|
||||
if c <= MinWStringCap {
|
||||
c = MinWStringCap
|
||||
}
|
||||
// allocate at-least double buffer size, as is done in [bytes.Buffer] and other places
|
||||
if c <= 2*b.Cap() {
|
||||
c = 2 * b.Cap()
|
||||
}
|
||||
|
||||
b2 := make([]uint16, c)
|
||||
if !b.empty() {
|
||||
copy(b2, b.b)
|
||||
freeBuffer(b.b)
|
||||
}
|
||||
b.b = b2
|
||||
return c
|
||||
}
|
||||
|
||||
// Buffer returns the underlying []uint16 buffer.
|
||||
func (b *WString) Buffer() []uint16 {
|
||||
if b.empty() {
|
||||
return nil
|
||||
}
|
||||
return b.b
|
||||
}
|
||||
|
||||
// Pointer returns a pointer to the first uint16 in the buffer.
|
||||
// If the [WString.Free] has already been called, the pointer will be nil.
|
||||
func (b *WString) Pointer() *uint16 {
|
||||
if b.empty() {
|
||||
return nil
|
||||
}
|
||||
return &b.b[0]
|
||||
}
|
||||
|
||||
// String returns the returns the UTF-8 encoding of the UTF-16 string in the buffer.
|
||||
//
|
||||
// It assumes that the data is null-terminated.
|
||||
func (b *WString) String() string {
|
||||
// Using [windows.UTF16ToString] would require importing "golang.org/x/sys/windows"
|
||||
// and would make this code Windows-only, which makes no sense.
|
||||
// So copy UTF16ToString code into here.
|
||||
// If other windows-specific code is added, switch to [windows.UTF16ToString]
|
||||
|
||||
s := b.b
|
||||
for i, v := range s {
|
||||
if v == 0 {
|
||||
s = s[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
return string(utf16.Decode(s))
|
||||
}
|
||||
|
||||
// Cap returns the underlying buffer capacity.
|
||||
func (b *WString) Cap() uint32 {
|
||||
if b.empty() {
|
||||
return 0
|
||||
}
|
||||
return b.cap()
|
||||
}
|
||||
|
||||
func (b *WString) cap() uint32 { return uint32(cap(b.b)) }
|
||||
func (b *WString) empty() bool { return b == nil || b.cap() == 0 }
|
||||
22
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
22
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
@@ -16,11 +16,12 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/Microsoft/go-winio/internal/fs"
|
||||
)
|
||||
|
||||
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
|
||||
//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
|
||||
//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW
|
||||
//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
|
||||
//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
|
||||
//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
|
||||
@@ -163,19 +164,21 @@ func (s pipeAddress) String() string {
|
||||
}
|
||||
|
||||
// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
|
||||
func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) {
|
||||
func tryDialPipe(ctx context.Context, path *string, access fs.AccessMask) (syscall.Handle, error) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return syscall.Handle(0), ctx.Err()
|
||||
default:
|
||||
h, err := createFile(*path,
|
||||
wh, err := fs.CreateFile(*path,
|
||||
access,
|
||||
0,
|
||||
nil,
|
||||
syscall.OPEN_EXISTING,
|
||||
windows.FILE_FLAG_OVERLAPPED|windows.SECURITY_SQOS_PRESENT|windows.SECURITY_ANONYMOUS,
|
||||
0)
|
||||
0, // mode
|
||||
nil, // security attributes
|
||||
fs.OPEN_EXISTING,
|
||||
fs.FILE_FLAG_OVERLAPPED|fs.SECURITY_SQOS_PRESENT|fs.SECURITY_ANONYMOUS,
|
||||
0, // template file handle
|
||||
)
|
||||
h := syscall.Handle(wh)
|
||||
if err == nil {
|
||||
return h, nil
|
||||
}
|
||||
@@ -219,7 +222,7 @@ func DialPipeContext(ctx context.Context, path string) (net.Conn, error) {
|
||||
func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) {
|
||||
var err error
|
||||
var h syscall.Handle
|
||||
h, err = tryDialPipe(ctx, &path, access)
|
||||
h, err = tryDialPipe(ctx, &path, fs.AccessMask(access))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -279,6 +282,7 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
|
||||
}
|
||||
defer localFree(ntPath.Buffer)
|
||||
oa.ObjectName = &ntPath
|
||||
oa.Attributes = windows.OBJ_CASE_INSENSITIVE
|
||||
|
||||
// The security descriptor is only needed for the first pipe.
|
||||
if first {
|
||||
|
||||
2
vendor/github.com/Microsoft/go-winio/pkg/etw/eventdescriptor.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/pkg/etw/eventdescriptor.go
generated
vendored
@@ -47,8 +47,6 @@ const (
|
||||
)
|
||||
|
||||
// EventDescriptor represents various metadata for an ETW event.
|
||||
//
|
||||
//nolint:structcheck // task is currently unused
|
||||
type eventDescriptor struct {
|
||||
id uint16
|
||||
version uint8
|
||||
|
||||
2
vendor/github.com/Microsoft/go-winio/pkg/fs/doc.go
generated
vendored
Normal file
2
vendor/github.com/Microsoft/go-winio/pkg/fs/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// This package contains Win32 filesystem functionality.
|
||||
package fs
|
||||
17
vendor/github.com/Microsoft/go-winio/pkg/fs/fs_windows.go
generated
vendored
17
vendor/github.com/Microsoft/go-winio/pkg/fs/fs_windows.go
generated
vendored
@@ -5,6 +5,8 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/Microsoft/go-winio/internal/stringbuffer"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -13,19 +15,18 @@ var (
|
||||
)
|
||||
|
||||
// GetFileSystemType obtains the type of a file system through GetVolumeInformation.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationw
|
||||
func GetFileSystemType(path string) (fsType string, err error) {
|
||||
drive := filepath.VolumeName(path)
|
||||
if len(drive) != 2 {
|
||||
return "", ErrInvalidPath
|
||||
}
|
||||
|
||||
var (
|
||||
buf = make([]uint16, 255)
|
||||
size = uint32(windows.MAX_PATH + 1)
|
||||
)
|
||||
buf := stringbuffer.NewWString()
|
||||
defer buf.Free()
|
||||
|
||||
drive += `\`
|
||||
err = windows.GetVolumeInformation(windows.StringToUTF16Ptr(drive), nil, 0, nil, nil, nil, &buf[0], size)
|
||||
fsType = windows.UTF16ToString(buf)
|
||||
return fsType, err
|
||||
err = windows.GetVolumeInformation(windows.StringToUTF16Ptr(drive), nil, 0, nil, nil, nil, buf.Pointer(), buf.Cap())
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
128
vendor/github.com/Microsoft/go-winio/pkg/fs/resolve.go
generated
vendored
Normal file
128
vendor/github.com/Microsoft/go-winio/pkg/fs/resolve.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
//go:build windows
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/Microsoft/go-winio/internal/fs"
|
||||
)
|
||||
|
||||
// ResolvePath returns the final path to a file or directory represented, resolving symlinks,
|
||||
// handling mount points, etc.
|
||||
// The resolution works by using the Windows API GetFinalPathNameByHandle, which takes a
|
||||
// handle and returns the final path to that file.
|
||||
//
|
||||
// It is intended to address short-comings of [filepath.EvalSymlinks], which does not work
|
||||
// well on Windows.
|
||||
func ResolvePath(path string) (string, error) {
|
||||
// We are not able to use builtin Go functionality for opening a directory path:
|
||||
// - os.Open on a directory returns a os.File where Fd() is a search handle from FindFirstFile.
|
||||
// - syscall.Open does not provide a way to specify FILE_FLAG_BACKUP_SEMANTICS, which is needed to
|
||||
// open a directory.
|
||||
//
|
||||
// We could use os.Open if the path is a file, but it's easier to just use the same code for both.
|
||||
// Therefore, we call windows.CreateFile directly.
|
||||
h, err := fs.CreateFile(
|
||||
path,
|
||||
fs.FILE_ANY_ACCESS, // access
|
||||
fs.FILE_SHARE_READ|fs.FILE_SHARE_WRITE|fs.FILE_SHARE_DELETE,
|
||||
nil, // security attributes
|
||||
fs.OPEN_EXISTING,
|
||||
fs.FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory handle.
|
||||
fs.NullHandle, // template file
|
||||
)
|
||||
if err != nil {
|
||||
return "", &os.PathError{
|
||||
Op: "CreateFile",
|
||||
Path: path,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
defer windows.CloseHandle(h) //nolint:errcheck
|
||||
|
||||
// We use the Windows API GetFinalPathNameByHandle to handle path resolution. GetFinalPathNameByHandle
|
||||
// returns a resolved path name for a file or directory. The returned path can be in several different
|
||||
// formats, based on the flags passed. There are several goals behind the design here:
|
||||
// - Do as little manual path manipulation as possible. Since Windows path formatting can be quite
|
||||
// complex, we try to just let the Windows APIs handle that for us.
|
||||
// - Retain as much compatibility with existing Go path functions as we can. In particular, we try to
|
||||
// ensure paths returned from resolvePath can be passed to EvalSymlinks.
|
||||
//
|
||||
// First, we query for the VOLUME_NAME_GUID path of the file. This will return a path in the form
|
||||
// "\\?\Volume{8a25748f-cf34-4ac6-9ee2-c89400e886db}\dir\file.txt". If the path is a UNC share
|
||||
// (e.g. "\\server\share\dir\file.txt"), then the VOLUME_NAME_GUID query will fail with ERROR_PATH_NOT_FOUND.
|
||||
// In this case, we will next try a VOLUME_NAME_DOS query. This query will return a path for a UNC share
|
||||
// in the form "\\?\UNC\server\share\dir\file.txt". This path will work with most functions, but EvalSymlinks
|
||||
// fails on it. Therefore, we rewrite the path to the form "\\server\share\dir\file.txt" before returning it.
|
||||
// This path rewrite may not be valid in all cases (see the notes in the next paragraph), but those should
|
||||
// be very rare edge cases, and this case wouldn't have worked with EvalSymlinks anyways.
|
||||
//
|
||||
// The "\\?\" prefix indicates that no path parsing or normalization should be performed by Windows.
|
||||
// Instead the path is passed directly to the object manager. The lack of parsing means that "." and ".." are
|
||||
// interpreted literally and "\"" must be used as a path separator. Additionally, because normalization is
|
||||
// not done, certain paths can only be represented in this format. For instance, "\\?\C:\foo." (with a trailing .)
|
||||
// cannot be written as "C:\foo.", because path normalization will remove the trailing ".".
|
||||
//
|
||||
// FILE_NAME_NORMALIZED can fail on some UNC paths based on access restrictions.
|
||||
// Attempt to query with FILE_NAME_NORMALIZED, and then fall back on FILE_NAME_OPENED if access is denied.
|
||||
//
|
||||
// Querying for VOLUME_NAME_DOS first instead of VOLUME_NAME_GUID would yield a "nicer looking" path in some cases.
|
||||
// For instance, it could return "\\?\C:\dir\file.txt" instead of "\\?\Volume{8a25748f-cf34-4ac6-9ee2-c89400e886db}\dir\file.txt".
|
||||
// However, we query for VOLUME_NAME_GUID first for two reasons:
|
||||
// - The volume GUID path is more stable. A volume's mount point can change when it is remounted, but its
|
||||
// volume GUID should not change.
|
||||
// - If the volume is mounted at a non-drive letter path (e.g. mounted to "C:\mnt"), then VOLUME_NAME_DOS
|
||||
// will return the mount path. EvalSymlinks fails on a path like this due to a bug.
|
||||
//
|
||||
// References:
|
||||
// - GetFinalPathNameByHandle: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlea
|
||||
// - Naming Files, Paths, and Namespaces: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
|
||||
// - Naming a Volume: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-volume
|
||||
|
||||
normalize := true
|
||||
guid := true
|
||||
rPath := ""
|
||||
for i := 1; i <= 4; i++ { // maximum of 4 different cases to try
|
||||
var flags fs.GetFinalPathFlag
|
||||
if normalize {
|
||||
flags |= fs.FILE_NAME_NORMALIZED // nop; for clarity
|
||||
} else {
|
||||
flags |= fs.FILE_NAME_OPENED
|
||||
}
|
||||
|
||||
if guid {
|
||||
flags |= fs.VOLUME_NAME_GUID
|
||||
} else {
|
||||
flags |= fs.VOLUME_NAME_DOS // nop; for clarity
|
||||
}
|
||||
|
||||
rPath, err = fs.GetFinalPathNameByHandle(h, flags)
|
||||
switch {
|
||||
case guid && errors.Is(err, windows.ERROR_PATH_NOT_FOUND):
|
||||
// ERROR_PATH_NOT_FOUND is returned from the VOLUME_NAME_GUID query if the path is a
|
||||
// network share (UNC path). In this case, query for the DOS name instead.
|
||||
guid = false
|
||||
continue
|
||||
case normalize && errors.Is(err, windows.ERROR_ACCESS_DENIED):
|
||||
// normalization failed when accessing individual components along path for SMB share
|
||||
normalize = false
|
||||
continue
|
||||
default:
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if err == nil && strings.HasPrefix(rPath, `\\?\UNC\`) {
|
||||
// Convert \\?\UNC\server\share -> \\server\share. The \\?\UNC syntax does not work with
|
||||
// some Go filepath functions such as EvalSymlinks. In the future if other components
|
||||
// move away from EvalSymlinks and use GetFinalPathNameByHandle instead, we could remove
|
||||
// this path munging.
|
||||
rPath = `\\` + rPath[len(`\\?\UNC\`):]
|
||||
}
|
||||
return rPath, err
|
||||
}
|
||||
2
vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go
generated
vendored
@@ -21,7 +21,6 @@ type (
|
||||
trusteeForm uint32
|
||||
trusteeType uint32
|
||||
|
||||
//nolint:structcheck // structcheck thinks fields are unused, but the are used to pass data to OS
|
||||
explicitAccess struct {
|
||||
accessPermissions accessMask
|
||||
accessMode accessMode
|
||||
@@ -29,7 +28,6 @@ type (
|
||||
trustee trustee
|
||||
}
|
||||
|
||||
//nolint:structcheck,unused // structcheck thinks fields are unused, but the are used to pass data to OS
|
||||
trustee struct {
|
||||
multipleTrustee *trustee
|
||||
multipleTrusteeOperation int32
|
||||
|
||||
85
vendor/github.com/Microsoft/go-winio/tools/mkwinsyscall/mkwinsyscall.go
generated
vendored
85
vendor/github.com/Microsoft/go-winio/tools/mkwinsyscall/mkwinsyscall.go
generated
vendored
@@ -477,15 +477,14 @@ func newFn(s string) (*Fn, error) {
|
||||
return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
||||
}
|
||||
s = trim(s[1:])
|
||||
a := strings.Split(s, ".")
|
||||
switch len(a) {
|
||||
case 1:
|
||||
f.dllfuncname = a[0]
|
||||
case 2:
|
||||
f.dllname = a[0]
|
||||
f.dllfuncname = a[1]
|
||||
default:
|
||||
return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
||||
if i := strings.LastIndex(s, "."); i >= 0 {
|
||||
f.dllname = s[:i]
|
||||
f.dllfuncname = s[i+1:]
|
||||
} else {
|
||||
f.dllfuncname = s
|
||||
}
|
||||
if f.dllfuncname == "" {
|
||||
return nil, fmt.Errorf("function name is not specified in %q", s)
|
||||
}
|
||||
if n := f.dllfuncname; endsIn(n, '?') {
|
||||
f.dllfuncname = n[:len(n)-1]
|
||||
@@ -502,7 +501,23 @@ func (f *Fn) DLLName() string {
|
||||
return f.dllname
|
||||
}
|
||||
|
||||
// DLLName returns DLL function name for function f.
|
||||
// DLLVar returns a valid Go identifier that represents DLLName.
|
||||
func (f *Fn) DLLVar() string {
|
||||
id := strings.Map(func(r rune) rune {
|
||||
switch r {
|
||||
case '.', '-':
|
||||
return '_'
|
||||
default:
|
||||
return r
|
||||
}
|
||||
}, f.DLLName())
|
||||
if !token.IsIdentifier(id) {
|
||||
panic(fmt.Errorf("could not create Go identifier for DLLName %q", f.DLLName()))
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// DLLFuncName returns DLL function name for function f.
|
||||
func (f *Fn) DLLFuncName() string {
|
||||
if f.dllfuncname == "" {
|
||||
return f.Name
|
||||
@@ -648,6 +663,13 @@ func (f *Fn) HelperName() string {
|
||||
return "_" + f.Name
|
||||
}
|
||||
|
||||
// DLL is a DLL's filename and a string that is valid in a Go identifier that should be used when
|
||||
// naming a variable that refers to the DLL.
|
||||
type DLL struct {
|
||||
Name string
|
||||
Var string
|
||||
}
|
||||
|
||||
// Source files and functions.
|
||||
type Source struct {
|
||||
Funcs []*Fn
|
||||
@@ -697,18 +719,20 @@ func ParseFiles(fs []string) (*Source, error) {
|
||||
}
|
||||
|
||||
// DLLs return dll names for a source set src.
|
||||
func (src *Source) DLLs() []string {
|
||||
func (src *Source) DLLs() []DLL {
|
||||
uniq := make(map[string]bool)
|
||||
r := make([]string, 0)
|
||||
r := make([]DLL, 0)
|
||||
for _, f := range src.Funcs {
|
||||
name := f.DLLName()
|
||||
if _, found := uniq[name]; !found {
|
||||
uniq[name] = true
|
||||
r = append(r, name)
|
||||
id := f.DLLVar()
|
||||
if _, found := uniq[id]; !found {
|
||||
uniq[id] = true
|
||||
r = append(r, DLL{f.DLLName(), id})
|
||||
}
|
||||
}
|
||||
if *sortdecls {
|
||||
sort.Strings(r)
|
||||
sort.Slice(r, func(i, j int) bool {
|
||||
return r[i].Var < r[j].Var
|
||||
})
|
||||
}
|
||||
return r
|
||||
}
|
||||
@@ -878,6 +902,22 @@ func (src *Source) Generate(w io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeTempSourceFile(data []byte) (string, error) {
|
||||
f, err := os.CreateTemp("", "mkwinsyscall-generated-*.go")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_, err = f.Write(data)
|
||||
if closeErr := f.Close(); err == nil {
|
||||
err = closeErr
|
||||
}
|
||||
if err != nil {
|
||||
os.Remove(f.Name()) // best effort
|
||||
return "", err
|
||||
}
|
||||
return f.Name(), nil
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: mkwinsyscall [flags] [path ...]\n")
|
||||
flag.PrintDefaults()
|
||||
@@ -904,7 +944,12 @@ func main() {
|
||||
|
||||
data, err := format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Printf("failed to format source: %v", err)
|
||||
f, err := writeTempSourceFile(buf.Bytes())
|
||||
if err != nil {
|
||||
log.Fatalf("failed to write unformatted source to file: %v", err)
|
||||
}
|
||||
log.Fatalf("for diagnosis, wrote unformatted source to %v", f)
|
||||
}
|
||||
if *filename == "" {
|
||||
_, err = os.Stdout.Write(data)
|
||||
@@ -970,10 +1015,10 @@ var (
|
||||
|
||||
{{/* help functions */}}
|
||||
|
||||
{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{newlazydll .}}
|
||||
{{define "dlls"}}{{range .DLLs}} mod{{.Var}} = {{newlazydll .Name}}
|
||||
{{end}}{{end}}
|
||||
|
||||
{{define "funcnames"}}{{range .DLLFuncNames}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}")
|
||||
{{define "funcnames"}}{{range .DLLFuncNames}} proc{{.DLLFuncName}} = mod{{.DLLVar}}.NewProc("{{.DLLFuncName}}")
|
||||
{{end}}{{end}}
|
||||
|
||||
{{define "helperbody"}}
|
||||
|
||||
19
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
19
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
@@ -63,7 +63,6 @@ var (
|
||||
procBackupWrite = modkernel32.NewProc("BackupWrite")
|
||||
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
|
||||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
|
||||
@@ -305,24 +304,6 @@ func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile)
|
||||
}
|
||||
|
||||
func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == syscall.InvalidHandle {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
|
||||
newport = syscall.Handle(r0)
|
||||
|
||||
4
vendor/github.com/Microsoft/hcsshim/.gitignore
generated
vendored
4
vendor/github.com/Microsoft/hcsshim/.gitignore
generated
vendored
@@ -37,6 +37,10 @@ rootfs-conv/*
|
||||
deps/*
|
||||
out/*
|
||||
|
||||
# protobuf files
|
||||
# only files at root of the repo, otherwise this will cause issues with vendoring
|
||||
/protobuf/*
|
||||
|
||||
# test results
|
||||
test/results
|
||||
|
||||
|
||||
6
vendor/github.com/Microsoft/hcsshim/.golangci.yml
generated
vendored
6
vendor/github.com/Microsoft/hcsshim/.golangci.yml
generated
vendored
@@ -135,3 +135,9 @@ issues:
|
||||
linters:
|
||||
- stylecheck
|
||||
Text: "ST1003:"
|
||||
|
||||
# v0 APIs are deprecated, but still retained for backwards compatability
|
||||
- path: cmd\\ncproxy\\
|
||||
linters:
|
||||
- staticcheck
|
||||
text: "^SA1019: (ncproxygrpcv0|nodenetsvcV0)"
|
||||
|
||||
18
vendor/github.com/Microsoft/hcsshim/Makefile
generated
vendored
18
vendor/github.com/Microsoft/hcsshim/Makefile
generated
vendored
@@ -94,23 +94,9 @@ out/delta.tar.gz: bin/init bin/vsockexec bin/cmd/gcs bin/cmd/gcstools bin/cmd/ho
|
||||
tar -zcf $@ -C rootfs .
|
||||
rm -rf rootfs
|
||||
|
||||
-include deps/cmd/gcs.gomake
|
||||
-include deps/cmd/gcstools.gomake
|
||||
-include deps/cmd/hooks/wait-paths.gomake
|
||||
-include deps/cmd/tar2ext4.gomake
|
||||
-include deps/internal/tools/snp-report.gomake
|
||||
|
||||
# Implicit rule for includes that define Go targets.
|
||||
%.gomake: $(SRCROOT)/Makefile
|
||||
bin/cmd/gcs bin/cmd/gcstools bin/cmd/hooks/wait-paths bin/cmd/tar2ext4 bin/internal/tools/snp-report:
|
||||
@mkdir -p $(dir $@)
|
||||
@/bin/echo $(@:deps/%.gomake=bin/%): $(SRCROOT)/hack/gomakedeps.sh > $@.new
|
||||
@/bin/echo -e '\t@mkdir -p $$(dir $$@) $(dir $@)' >> $@.new
|
||||
@/bin/echo -e '\t$$(GO_BUILD) -o $$@.new $$(SRCROOT)/$$(@:bin/%=%)' >> $@.new
|
||||
@/bin/echo -e '\tGO="$(GO)" $$(SRCROOT)/hack/gomakedeps.sh $$@ $$(SRCROOT)/$$(@:bin/%=%) $$(GO_FLAGS) $$(GO_FLAGS_EXTRA) > $(@:%.gomake=%.godeps).new' >> $@.new
|
||||
@/bin/echo -e '\tmv $(@:%.gomake=%.godeps).new $(@:%.gomake=%.godeps)' >> $@.new
|
||||
@/bin/echo -e '\tmv $$@.new $$@' >> $@.new
|
||||
@/bin/echo -e '-include $(@:%.gomake=%.godeps)' >> $@.new
|
||||
mv $@.new $@
|
||||
GOOS=linux $(GO_BUILD) -o $@ $(SRCROOT)/$(@:bin/%=%)
|
||||
|
||||
bin/vsockexec: vsockexec/vsockexec.o vsockexec/vsock.o
|
||||
@mkdir -p bin
|
||||
|
||||
4
vendor/github.com/Microsoft/hcsshim/Protobuild.toml
generated
vendored
4
vendor/github.com/Microsoft/hcsshim/Protobuild.toml
generated
vendored
@@ -9,6 +9,10 @@ plugins = ["grpc", "fieldpath"]
|
||||
# treat the root of the project as an include, but this may not be necessary.
|
||||
before = ["./protobuf"]
|
||||
|
||||
# defaults are "/usr/local/include" and "/usr/include", which don't exist on Windows.
|
||||
# override defaults to supress errors about non-existant directories.
|
||||
after = []
|
||||
|
||||
# Paths that should be treated as include roots in relation to the vendor
|
||||
# directory. These will be calculated with the vendor directory nearest the
|
||||
# target package.
|
||||
|
||||
44
vendor/github.com/Microsoft/hcsshim/ext4/dmverity/dmverity.go
generated
vendored
44
vendor/github.com/Microsoft/hcsshim/ext4/dmverity/dmverity.go
generated
vendored
@@ -178,29 +178,35 @@ func ReadDMVerityInfo(vhdPath string, offsetInBytes int64) (*VerityInfo, error)
|
||||
return nil, errors.Errorf("failed to seek dm-verity super block: expected bytes=%d, actual=%d", offsetInBytes, s)
|
||||
}
|
||||
|
||||
return ReadDMVerityInfoReader(vhd)
|
||||
}
|
||||
|
||||
func ReadDMVerityInfoReader(r io.Reader) (*VerityInfo, error) {
|
||||
block := make([]byte, blockSize)
|
||||
if s, err := vhd.Read(block); err != nil || s != blockSize {
|
||||
if s, err := r.Read(block); err != nil || s != blockSize {
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "%s", ErrSuperBlockReadFailure)
|
||||
return nil, fmt.Errorf("%s: %w", ErrSuperBlockReadFailure, err)
|
||||
}
|
||||
return nil, errors.Wrapf(ErrSuperBlockReadFailure, "unexpected bytes read: expected=%d, actual=%d", blockSize, s)
|
||||
return nil, fmt.Errorf("unexpected bytes read expected=%d actual=%d: %w", blockSize, s, ErrSuperBlockReadFailure)
|
||||
}
|
||||
|
||||
dmvSB := &dmveritySuperblock{}
|
||||
b := bytes.NewBuffer(block)
|
||||
if err := binary.Read(b, binary.LittleEndian, dmvSB); err != nil {
|
||||
return nil, errors.Wrapf(err, "%s", ErrSuperBlockParseFailure)
|
||||
return nil, fmt.Errorf("%s: %w", ErrSuperBlockParseFailure, err)
|
||||
}
|
||||
|
||||
if string(bytes.Trim(dmvSB.Signature[:], "\x00")[:]) != VeritySignature {
|
||||
return nil, ErrNotVeritySuperBlock
|
||||
}
|
||||
// read the merkle tree root
|
||||
if s, err := vhd.Read(block); err != nil || s != blockSize {
|
||||
|
||||
if s, err := r.Read(block); err != nil || s != blockSize {
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "%s", ErrRootHashReadFailure)
|
||||
return nil, fmt.Errorf("%s: %w", ErrRootHashReadFailure, err)
|
||||
}
|
||||
return nil, errors.Wrapf(ErrRootHashReadFailure, "unexpected bytes read: expected=%d, actual=%d", blockSize, s)
|
||||
return nil, fmt.Errorf("unexpected bytes read expected=%d, actual=%d: %w", blockSize, s, ErrRootHashReadFailure)
|
||||
}
|
||||
|
||||
rootHash := hash2(dmvSB.Salt[:dmvSB.SaltSize], block)
|
||||
return &VerityInfo{
|
||||
RootDigest: fmt.Sprintf("%x", rootHash),
|
||||
@@ -215,12 +221,21 @@ func ReadDMVerityInfo(vhdPath string, offsetInBytes int64) (*VerityInfo, error)
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ComputeAndWriteHashDevice builds merkle tree from a given io.ReadSeeker and writes the result
|
||||
// hash device (dm-verity super-block combined with merkle tree) to io.WriteSeeker.
|
||||
func ComputeAndWriteHashDevice(r io.ReadSeeker, w io.WriteSeeker) error {
|
||||
// ComputeAndWriteHashDevice builds merkle tree from a given io.ReadSeeker and
|
||||
// writes the result hash device (dm-verity super-block combined with merkle
|
||||
// tree) to io.Writer.
|
||||
func ComputeAndWriteHashDevice(r io.ReadSeeker, w io.Writer) error {
|
||||
// save current reader position
|
||||
currBytePos, err := r.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// reset to the beginning to find the device size
|
||||
if _, err := r.Seek(0, io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tree, err := MerkleTree(r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to build merkle tree")
|
||||
@@ -230,10 +245,13 @@ func ComputeAndWriteHashDevice(r io.ReadSeeker, w io.WriteSeeker) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dmVeritySB := NewDMVeritySuperblock(uint64(devSize))
|
||||
if _, err := w.Seek(0, io.SeekEnd); err != nil {
|
||||
|
||||
// reset reader to initial position
|
||||
if _, err := r.Seek(currBytePos, io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dmVeritySB := NewDMVeritySuperblock(uint64(devSize))
|
||||
if err := binary.Write(w, binary.LittleEndian, dmVeritySB); err != nil {
|
||||
return errors.Wrap(err, "failed to write dm-verity super-block")
|
||||
}
|
||||
|
||||
57
vendor/github.com/Microsoft/hcsshim/ext4/tar2ext4/tar2ext4.go
generated
vendored
57
vendor/github.com/Microsoft/hcsshim/ext4/tar2ext4/tar2ext4.go
generated
vendored
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/Microsoft/hcsshim/ext4/dmverity"
|
||||
"github.com/Microsoft/hcsshim/ext4/internal/compactext4"
|
||||
"github.com/Microsoft/hcsshim/ext4/internal/format"
|
||||
"github.com/Microsoft/hcsshim/internal/log"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -200,7 +201,19 @@ func Convert(r io.Reader, w io.ReadWriteSeeker, options ...Option) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadExt4SuperBlock reads and returns ext4 super block from VHD
|
||||
// ReadExt4SuperBlock reads and returns ext4 super block from given device.
|
||||
func ReadExt4SuperBlock(devicePath string) (*format.SuperBlock, error) {
|
||||
dev, err := os.OpenFile(devicePath, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer dev.Close()
|
||||
|
||||
return ReadExt4SuperBlockReadSeeker(dev)
|
||||
}
|
||||
|
||||
// ReadExt4SuperBlockReadSeeker reads and returns ext4 super block given
|
||||
// an io.ReadSeeker.
|
||||
//
|
||||
// The layout on disk is as follows:
|
||||
// | Group 0 padding | - 1024 bytes
|
||||
@@ -215,28 +228,56 @@ func Convert(r io.Reader, w io.ReadWriteSeeker, options ...Option) error {
|
||||
// More details can be found here https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout
|
||||
//
|
||||
// Our goal is to skip the Group 0 padding, read and return the ext4 SuperBlock
|
||||
func ReadExt4SuperBlock(vhdPath string) (*format.SuperBlock, error) {
|
||||
vhd, err := os.OpenFile(vhdPath, os.O_RDONLY, 0)
|
||||
func ReadExt4SuperBlockReadSeeker(rsc io.ReadSeeker) (*format.SuperBlock, error) {
|
||||
// save current reader position
|
||||
currBytePos, err := rsc.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer vhd.Close()
|
||||
|
||||
// Skip padding at the start
|
||||
if _, err := vhd.Seek(1024, io.SeekStart); err != nil {
|
||||
if _, err := rsc.Seek(1024, io.SeekCurrent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var sb format.SuperBlock
|
||||
if err := binary.Read(vhd, binary.LittleEndian, &sb); err != nil {
|
||||
if err := binary.Read(rsc, binary.LittleEndian, &sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Make sure the magic bytes are correct.
|
||||
|
||||
// reset the reader to initial position
|
||||
if _, err := rsc.Seek(currBytePos, io.SeekStart); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if sb.Magic != format.SuperBlockMagic {
|
||||
return nil, errors.New("not an ext4 file system")
|
||||
}
|
||||
return &sb, nil
|
||||
}
|
||||
|
||||
// IsDeviceExt4 is will read the device's superblock and determine if it is
|
||||
// and ext4 superblock.
|
||||
func IsDeviceExt4(devicePath string) bool {
|
||||
// ReadExt4SuperBlock will check the superblock magic number for us,
|
||||
// so we know if no error is returned, this is an ext4 device.
|
||||
_, err := ReadExt4SuperBlock(devicePath)
|
||||
if err != nil {
|
||||
log.L.Warnf("failed to read Ext4 superblock: %s", err)
|
||||
}
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Ext4FileSystemSize reads ext4 superblock and returns the size of the underlying
|
||||
// ext4 file system and its block size.
|
||||
func Ext4FileSystemSize(r io.ReadSeeker) (int64, int, error) {
|
||||
sb, err := ReadExt4SuperBlockReadSeeker(r)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to read ext4 superblock: %w", err)
|
||||
}
|
||||
blockSize := 1024 * (1 << sb.LogBlockSize)
|
||||
fsSize := int64(blockSize) * int64(sb.BlocksCountLow)
|
||||
return fsSize, blockSize, nil
|
||||
}
|
||||
|
||||
// ConvertAndComputeRootDigest writes a compact ext4 file system image that contains the files in the
|
||||
// input tar stream, computes the resulting file image's cryptographic hashes (merkle tree) and returns
|
||||
// merkle tree root digest. Convert is called with minimal options: ConvertWhiteout and MaximumDiskSize
|
||||
|
||||
85
vendor/github.com/Microsoft/hcsshim/internal/log/format.go
generated
vendored
Normal file
85
vendor/github.com/Microsoft/hcsshim/internal/log/format.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
)
|
||||
|
||||
const TimeFormat = log.RFC3339NanoFixed
|
||||
|
||||
func FormatTime(t time.Time) string {
|
||||
return t.Format(TimeFormat)
|
||||
}
|
||||
|
||||
// DurationFormat formats a [time.Duration] log entry.
|
||||
//
|
||||
// A nil value signals an error with the formatting.
|
||||
type DurationFormat func(time.Duration) interface{}
|
||||
|
||||
func DurationFormatString(d time.Duration) interface{} { return d.String() }
|
||||
func DurationFormatSeconds(d time.Duration) interface{} { return d.Seconds() }
|
||||
func DurationFormatMilliseconds(d time.Duration) interface{} { return d.Milliseconds() }
|
||||
|
||||
// FormatIO formats net.Conn and other types that have an `Addr()` or `Name()`.
|
||||
//
|
||||
// See FormatEnabled for more information.
|
||||
func FormatIO(ctx context.Context, v interface{}) string {
|
||||
m := make(map[string]string)
|
||||
m["type"] = reflect.TypeOf(v).String()
|
||||
|
||||
switch t := v.(type) {
|
||||
case net.Conn:
|
||||
m["localAddress"] = formatAddr(t.LocalAddr())
|
||||
m["remoteAddress"] = formatAddr(t.RemoteAddr())
|
||||
case interface{ Addr() net.Addr }:
|
||||
m["address"] = formatAddr(t.Addr())
|
||||
default:
|
||||
return Format(ctx, t)
|
||||
}
|
||||
|
||||
return Format(ctx, m)
|
||||
}
|
||||
|
||||
func formatAddr(a net.Addr) string {
|
||||
return a.Network() + "://" + a.String()
|
||||
}
|
||||
|
||||
// Format formats an object into a JSON string, without any indendtation or
|
||||
// HTML escapes.
|
||||
// Context is used to output a log waring if the conversion fails.
|
||||
//
|
||||
// This is intended primarily for `trace.StringAttribute()`
|
||||
func Format(ctx context.Context, v interface{}) string {
|
||||
b, err := encode(v)
|
||||
if err != nil {
|
||||
G(ctx).WithError(err).Warning("could not format value")
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func encode(v interface{}) ([]byte, error) {
|
||||
return encodeBuffer(&bytes.Buffer{}, v)
|
||||
}
|
||||
|
||||
func encodeBuffer(buf *bytes.Buffer, v interface{}) ([]byte, error) {
|
||||
enc := json.NewEncoder(buf)
|
||||
enc.SetEscapeHTML(false)
|
||||
enc.SetIndent("", "")
|
||||
|
||||
if err := enc.Encode(v); err != nil {
|
||||
err = fmt.Errorf("could not marshall %T to JSON for logging: %w", v, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// encoder.Encode appends a newline to the end
|
||||
return bytes.TrimSpace(buf.Bytes()), nil
|
||||
}
|
||||
145
vendor/github.com/Microsoft/hcsshim/internal/log/hook.go
generated
vendored
145
vendor/github.com/Microsoft/hcsshim/internal/log/hook.go
generated
vendored
@@ -1,23 +1,58 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/logfields"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// Hook serves to intercept and format `logrus.Entry`s before they are passed
|
||||
// to the ETW hook.
|
||||
const nullString = "null"
|
||||
|
||||
// Hook intercepts and formats a [logrus.Entry] before it logged.
|
||||
//
|
||||
// The containerd shim discards the (formatted) logrus output, and outputs only via ETW.
|
||||
// The Linux GCS outputs logrus entries over stdout, which is consumed by the shim and
|
||||
// then re-output via the ETW hook.
|
||||
type Hook struct{}
|
||||
// The shim either outputs the logs through an ETW hook, discarding the (formatted) output
|
||||
// or logs output to a pipe for logging binaries to consume.
|
||||
// The Linux GCS outputs logrus entries over stdout, which is then consumed and re-output
|
||||
// by the shim.
|
||||
type Hook struct {
|
||||
// EncodeAsJSON formats structs, maps, arrays, slices, and [bytes.Buffer] as JSON.
|
||||
// Variables of [bytes.Buffer] will be converted to []byte.
|
||||
//
|
||||
// Default is false.
|
||||
EncodeAsJSON bool
|
||||
|
||||
// FormatTime specifies the format for [time.Time] variables.
|
||||
// An empty string disables formatting.
|
||||
// When disabled, the fall back will the JSON encoding, if enabled.
|
||||
//
|
||||
// Default is [github.com/containerd/containerd/log.RFC3339NanoFixed].
|
||||
TimeFormat string
|
||||
|
||||
// Duration format converts a [time.Duration] fields to an appropriate encoding.
|
||||
// nil disables formatting.
|
||||
// When disabled, the fall back will the JSON encoding, if enabled.
|
||||
//
|
||||
// Default is [DurationFormatString], which appends a duration unit after the value.
|
||||
DurationFormat DurationFormat
|
||||
|
||||
// AddSpanContext adds [logfields.TraceID] and [logfields.SpanID] fields to
|
||||
// the entry from the span context stored in [logrus.Entry.Context], if it exists.
|
||||
AddSpanContext bool
|
||||
}
|
||||
|
||||
var _ logrus.Hook = &Hook{}
|
||||
|
||||
func NewHook() *Hook {
|
||||
return &Hook{}
|
||||
return &Hook{
|
||||
TimeFormat: log.RFC3339NanoFixed,
|
||||
DurationFormat: DurationFormatString,
|
||||
AddSpanContext: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Hook) Levels() []logrus.Level {
|
||||
@@ -25,14 +60,108 @@ func (h *Hook) Levels() []logrus.Level {
|
||||
}
|
||||
|
||||
func (h *Hook) Fire(e *logrus.Entry) (err error) {
|
||||
// JSON encode, if necessary, then add span information
|
||||
h.encode(e)
|
||||
h.addSpanContext(e)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// encode loops through all the fields in the [logrus.Entry] and encodes them according to
|
||||
// the settings in [Hook].
|
||||
// If [Hook.TimeFormat] is non-empty, it will be passed to [time.Time.Format] for
|
||||
// fields of type [time.Time].
|
||||
//
|
||||
// If [Hook.EncodeAsJSON] is true, then fields that are not numeric, boolean, strings, or
|
||||
// errors will be encoded via a [json.Marshal] (with HTML escaping disabled).
|
||||
// Chanel- and function-typed fields, as well as unsafe pointers are left alone and not encoded.
|
||||
//
|
||||
// If [Hook.TimeFormat] and [Hook.DurationFormat] are empty and [Hook.EncodeAsJSON] is false,
|
||||
// then this is a no-op.
|
||||
func (h *Hook) encode(e *logrus.Entry) {
|
||||
d := e.Data
|
||||
|
||||
formatTime := h.TimeFormat != ""
|
||||
formatDuration := h.DurationFormat != nil
|
||||
if !(h.EncodeAsJSON || formatTime || formatDuration) {
|
||||
return
|
||||
}
|
||||
|
||||
for k, v := range d {
|
||||
// encode types with dedicated formatting options first
|
||||
|
||||
if vv, ok := v.(time.Time); formatTime && ok {
|
||||
d[k] = vv.Format(h.TimeFormat)
|
||||
continue
|
||||
}
|
||||
|
||||
if vv, ok := v.(time.Duration); formatDuration && ok {
|
||||
d[k] = h.DurationFormat(vv)
|
||||
continue
|
||||
}
|
||||
|
||||
// general case JSON encoding
|
||||
|
||||
if !h.EncodeAsJSON {
|
||||
continue
|
||||
}
|
||||
|
||||
switch vv := v.(type) {
|
||||
// built in types
|
||||
// "json" marshals errors as "{}", so leave alone here
|
||||
case bool, string, error, uintptr,
|
||||
int8, int16, int32, int64, int,
|
||||
uint8, uint32, uint64, uint,
|
||||
float32, float64:
|
||||
continue
|
||||
|
||||
// Rather than setting d[k] = vv.String(), JSON encode []byte value, since it
|
||||
// may be a binary payload and not representable as a string.
|
||||
// `case bytes.Buffer,*bytes.Buffer:` resolves `vv` to `interface{}`,
|
||||
// so cannot use `vv.Bytes`.
|
||||
// Could move to below the `reflect.Indirect()` call below, but
|
||||
// that would require additional typematching and dereferencing.
|
||||
// Easier to keep these duplicate branches here.
|
||||
case bytes.Buffer:
|
||||
v = vv.Bytes()
|
||||
case *bytes.Buffer:
|
||||
v = vv.Bytes()
|
||||
}
|
||||
|
||||
// dereference pointer or interface variables
|
||||
rv := reflect.Indirect(reflect.ValueOf(v))
|
||||
// check if `v` is a null pointer
|
||||
if !rv.IsValid() {
|
||||
d[k] = nullString
|
||||
continue
|
||||
}
|
||||
|
||||
switch rv.Kind() {
|
||||
case reflect.Map, reflect.Struct, reflect.Array, reflect.Slice:
|
||||
default:
|
||||
// Bool, [U]?Int*, Float*, Complex*, Uintptr, String: encoded as normal
|
||||
// Chan, Func: not supported by json
|
||||
// Interface, Pointer: dereferenced above
|
||||
// UnsafePointer: not supported by json, not safe to de-reference; leave alone
|
||||
continue
|
||||
}
|
||||
|
||||
b, err := encode(v)
|
||||
if err != nil {
|
||||
// Errors are written to stderr (ie, to `panic.log`) and stops the remaining
|
||||
// hooks (ie, exporting to ETW) from firing. So add encoding errors to
|
||||
// the entry data to be written out, but keep on processing.
|
||||
d[k+"-"+logrus.ErrorKey] = err.Error()
|
||||
// keep the original `v` as the value,
|
||||
continue
|
||||
}
|
||||
d[k] = string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Hook) addSpanContext(e *logrus.Entry) {
|
||||
ctx := e.Context
|
||||
if ctx == nil {
|
||||
if !h.AddSpanContext || ctx == nil {
|
||||
return
|
||||
}
|
||||
span := trace.FromContext(ctx)
|
||||
|
||||
22
vendor/github.com/Microsoft/hcsshim/internal/log/scrub.go
generated
vendored
22
vendor/github.com/Microsoft/hcsshim/internal/log/scrub.go
generated
vendored
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2"
|
||||
@@ -56,11 +55,11 @@ func ScrubProcessParameters(s string) (string, error) {
|
||||
}
|
||||
pp.Environment = map[string]string{_scrubbedReplacement: _scrubbedReplacement}
|
||||
|
||||
buf := bytes.NewBuffer(b[:0])
|
||||
if err := encode(buf, pp); err != nil {
|
||||
b, err := encodeBuffer(bytes.NewBuffer(b[:0]), pp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(buf.String()), nil
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// ScrubBridgeCreate scrubs requests sent over the bridge of type
|
||||
@@ -150,21 +149,12 @@ func scrubBytes(b []byte, scrub scrubberFunc) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
if err := encode(buf, m); err != nil {
|
||||
b, err := encode(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bytes.TrimSpace(buf.Bytes()), nil
|
||||
}
|
||||
|
||||
func encode(buf *bytes.Buffer, v interface{}) error {
|
||||
enc := json.NewEncoder(buf)
|
||||
enc.SetEscapeHTML(false)
|
||||
if err := enc.Encode(v); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func isRequestBase(m genMap) bool {
|
||||
|
||||
69
vendor/github.com/Microsoft/hcsshim/internal/oc/errors.go
generated
vendored
Normal file
69
vendor/github.com/Microsoft/hcsshim/internal/oc/errors.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package oc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// todo: break import cycle with "internal/hcs/errors.go" and reference errors defined there
|
||||
// todo: add errors defined in "internal/guest/gcserror" (Hresult does not implement error)
|
||||
|
||||
func toStatusCode(err error) codes.Code {
|
||||
// checks if err implements GRPCStatus() *"google.golang.org/grpc/status".Status,
|
||||
// wraps an error defined in "github.com/containerd/containerd/errdefs", or is a
|
||||
// context timeout or cancelled error
|
||||
if s, ok := status.FromError(errdefs.ToGRPC(err)); ok {
|
||||
return s.Code()
|
||||
}
|
||||
|
||||
switch {
|
||||
// case isAny(err):
|
||||
// return codes.Cancelled
|
||||
case isAny(err, os.ErrInvalid):
|
||||
return codes.InvalidArgument
|
||||
case isAny(err, os.ErrDeadlineExceeded):
|
||||
return codes.DeadlineExceeded
|
||||
case isAny(err, os.ErrNotExist):
|
||||
return codes.NotFound
|
||||
case isAny(err, os.ErrExist):
|
||||
return codes.AlreadyExists
|
||||
case isAny(err, os.ErrPermission):
|
||||
return codes.PermissionDenied
|
||||
// case isAny(err):
|
||||
// return codes.ResourceExhausted
|
||||
case isAny(err, os.ErrClosed, net.ErrClosed, io.ErrClosedPipe, io.ErrShortBuffer):
|
||||
return codes.FailedPrecondition
|
||||
// case isAny(err):
|
||||
// return codes.Aborted
|
||||
// case isAny(err):
|
||||
// return codes.OutOfRange
|
||||
// case isAny(err):
|
||||
// return codes.Unimplemented
|
||||
case isAny(err, io.ErrNoProgress):
|
||||
return codes.Internal
|
||||
// case isAny(err):
|
||||
// return codes.Unavailable
|
||||
case isAny(err, io.ErrShortWrite, io.ErrUnexpectedEOF):
|
||||
return codes.DataLoss
|
||||
// case isAny(err):
|
||||
// return codes.Unauthenticated
|
||||
default:
|
||||
return codes.Unknown
|
||||
}
|
||||
}
|
||||
|
||||
// isAny returns true if errors.Is is true for any of the provided errors, errs.
|
||||
func isAny(err error, errs ...error) bool {
|
||||
for _, e := range errs {
|
||||
if errors.Is(err, e) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
77
vendor/github.com/Microsoft/hcsshim/internal/oc/exporter.go
generated
vendored
77
vendor/github.com/Microsoft/hcsshim/internal/oc/exporter.go
generated
vendored
@@ -3,19 +3,26 @@ package oc
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
"google.golang.org/grpc/codes"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/log"
|
||||
"github.com/Microsoft/hcsshim/internal/logfields"
|
||||
)
|
||||
|
||||
var _ = (trace.Exporter)(&LogrusExporter{})
|
||||
const spanMessage = "Span"
|
||||
|
||||
var _errorCodeKey = logrus.ErrorKey + "Code"
|
||||
|
||||
// LogrusExporter is an OpenCensus `trace.Exporter` that exports
|
||||
// `trace.SpanData` to logrus output.
|
||||
type LogrusExporter struct {
|
||||
}
|
||||
type LogrusExporter struct{}
|
||||
|
||||
var _ trace.Exporter = &LogrusExporter{}
|
||||
|
||||
// ExportSpan exports `s` based on the the following rules:
|
||||
//
|
||||
// 1. All output will contain `s.Attributes`, `s.TraceID`, `s.SpanID`,
|
||||
// `s.ParentSpanID` for correlation
|
||||
// 1. All output will contain `s.Attributes`, `s.SpanKind`, `s.TraceID`,
|
||||
// `s.SpanID`, and `s.ParentSpanID` for correlation
|
||||
//
|
||||
// 2. Any calls to .Annotate will not be supported.
|
||||
//
|
||||
@@ -23,21 +30,57 @@ type LogrusExporter struct {
|
||||
// `s.Status.Code != 0` in which case it will be written at `logrus.ErrorLevel`
|
||||
// providing `s.Status.Message` as the error value.
|
||||
func (le *LogrusExporter) ExportSpan(s *trace.SpanData) {
|
||||
// Combine all span annotations with traceID, spanID, parentSpanID
|
||||
baseEntry := logrus.WithFields(logrus.Fields(s.Attributes))
|
||||
baseEntry.Data["traceID"] = s.TraceID.String()
|
||||
baseEntry.Data["spanID"] = s.SpanID.String()
|
||||
baseEntry.Data["parentSpanID"] = s.ParentSpanID.String()
|
||||
baseEntry.Data["startTime"] = s.StartTime
|
||||
baseEntry.Data["endTime"] = s.EndTime
|
||||
baseEntry.Data["duration"] = s.EndTime.Sub(s.StartTime).String()
|
||||
baseEntry.Data["name"] = s.Name
|
||||
baseEntry.Time = s.StartTime
|
||||
if s.DroppedAnnotationCount > 0 {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"name": s.Name,
|
||||
logfields.TraceID: s.TraceID.String(),
|
||||
logfields.SpanID: s.SpanID.String(),
|
||||
"dropped": s.DroppedAttributeCount,
|
||||
"maxAttributes": len(s.Attributes),
|
||||
}).Warning("span had dropped attributes")
|
||||
}
|
||||
|
||||
entry := log.L.Dup()
|
||||
// Combine all span annotations with span data (eg, trace ID, span ID, parent span ID,
|
||||
// error, status code)
|
||||
// (OC) Span attributes are guaranteed to be strings, bools, or int64s, so we can
|
||||
// can skip overhead in entry.WithFields() and add them directly to entry.Data.
|
||||
// Preallocate ahead of time, since we should add, at most, 10 additional entries
|
||||
data := make(logrus.Fields, len(entry.Data)+len(s.Attributes)+10)
|
||||
|
||||
// Default log entry may have prexisting/application-wide data
|
||||
for k, v := range entry.Data {
|
||||
data[k] = v
|
||||
}
|
||||
for k, v := range s.Attributes {
|
||||
data[k] = v
|
||||
}
|
||||
|
||||
data[logfields.Name] = s.Name
|
||||
data[logfields.TraceID] = s.TraceID.String()
|
||||
data[logfields.SpanID] = s.SpanID.String()
|
||||
data[logfields.ParentSpanID] = s.ParentSpanID.String()
|
||||
data[logfields.StartTime] = s.StartTime
|
||||
data[logfields.EndTime] = s.EndTime
|
||||
data[logfields.Duration] = s.EndTime.Sub(s.StartTime)
|
||||
if sk := spanKindToString(s.SpanKind); sk != "" {
|
||||
data["spanKind"] = sk
|
||||
}
|
||||
|
||||
level := logrus.InfoLevel
|
||||
if s.Status.Code != 0 {
|
||||
level = logrus.ErrorLevel
|
||||
baseEntry.Data[logrus.ErrorKey] = s.Status.Message
|
||||
|
||||
// don't overwrite an existing "error" or "errorCode" attributes
|
||||
if _, ok := data[logrus.ErrorKey]; !ok {
|
||||
data[logrus.ErrorKey] = s.Status.Message
|
||||
}
|
||||
if _, ok := data[_errorCodeKey]; !ok {
|
||||
data[_errorCodeKey] = codes.Code(s.Status.Code).String()
|
||||
}
|
||||
}
|
||||
baseEntry.Log(level, "Span")
|
||||
|
||||
entry.Data = data
|
||||
entry.Time = s.StartTime
|
||||
entry.Log(level, spanMessage)
|
||||
}
|
||||
|
||||
14
vendor/github.com/Microsoft/hcsshim/internal/oc/span.go
generated
vendored
14
vendor/github.com/Microsoft/hcsshim/internal/oc/span.go
generated
vendored
@@ -14,8 +14,7 @@ var DefaultSampler = trace.AlwaysSample()
|
||||
func SetSpanStatus(span *trace.Span, err error) {
|
||||
status := trace.Status{}
|
||||
if err != nil {
|
||||
// TODO: JTERRY75 - Handle errors in a non-generic way
|
||||
status.Code = trace.StatusCodeUnknown
|
||||
status.Code = int32(toStatusCode(err))
|
||||
status.Message = err.Error()
|
||||
}
|
||||
span.SetStatus(status)
|
||||
@@ -46,3 +45,14 @@ func update(ctx context.Context, s *trace.Span) (context.Context, *trace.Span) {
|
||||
|
||||
var WithServerSpanKind = trace.WithSpanKind(trace.SpanKindServer)
|
||||
var WithClientSpanKind = trace.WithSpanKind(trace.SpanKindClient)
|
||||
|
||||
func spanKindToString(sk int) string {
|
||||
switch sk {
|
||||
case trace.SpanKindClient:
|
||||
return "client"
|
||||
case trace.SpanKindServer:
|
||||
return "server"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
14
vendor/github.com/Microsoft/hcsshim/internal/security/grantvmgroupaccess.go
generated
vendored
14
vendor/github.com/Microsoft/hcsshim/internal/security/grantvmgroupaccess.go
generated
vendored
@@ -23,20 +23,14 @@ type (
|
||||
)
|
||||
|
||||
type explicitAccess struct {
|
||||
//nolint:structcheck
|
||||
accessPermissions accessMask
|
||||
//nolint:structcheck
|
||||
accessMode accessMode
|
||||
//nolint:structcheck
|
||||
inheritance inheritMode
|
||||
//nolint:structcheck
|
||||
trustee trustee
|
||||
accessMode accessMode
|
||||
inheritance inheritMode
|
||||
trustee trustee
|
||||
}
|
||||
|
||||
type trustee struct {
|
||||
//nolint:unused,structcheck
|
||||
multipleTrustee *trustee
|
||||
//nolint:unused,structcheck
|
||||
multipleTrustee *trustee
|
||||
multipleTrusteeOperation int32
|
||||
trusteeForm trusteeForm
|
||||
trusteeType trusteeType
|
||||
|
||||
35
vendor/github.com/Microsoft/hcsshim/osversion/platform_compat_windows.go
generated
vendored
Normal file
35
vendor/github.com/Microsoft/hcsshim/osversion/platform_compat_windows.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
package osversion
|
||||
|
||||
// List of stable ABI compliant ltsc releases
|
||||
// Note: List must be sorted in ascending order
|
||||
var compatLTSCReleases = []uint16{
|
||||
V21H2Server,
|
||||
}
|
||||
|
||||
// CheckHostAndContainerCompat checks if given host and container
|
||||
// OS versions are compatible.
|
||||
// It includes support for stable ABI compliant versions as well.
|
||||
// Every release after WS 2022 will support the previous ltsc
|
||||
// container image. Stable ABI is in preview mode for windows 11 client.
|
||||
// Refer: https://learn.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility?tabs=windows-server-2022%2Cwindows-10#windows-server-host-os-compatibility
|
||||
func CheckHostAndContainerCompat(host, ctr OSVersion) bool {
|
||||
// check major minor versions of host and guest
|
||||
if host.MajorVersion != ctr.MajorVersion ||
|
||||
host.MinorVersion != ctr.MinorVersion {
|
||||
return false
|
||||
}
|
||||
|
||||
// If host is < WS 2022, exact version match is required
|
||||
if host.Build < V21H2Server {
|
||||
return host.Build == ctr.Build
|
||||
}
|
||||
|
||||
var supportedLtscRelease uint16
|
||||
for i := len(compatLTSCReleases) - 1; i >= 0; i-- {
|
||||
if host.Build >= compatLTSCReleases[i] {
|
||||
supportedLtscRelease = compatLTSCReleases[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
return ctr.Build >= supportedLtscRelease && ctr.Build <= host.Build
|
||||
}
|
||||
6
vendor/github.com/Microsoft/hcsshim/pkg/go-runhcs/runhcs.go
generated
vendored
6
vendor/github.com/Microsoft/hcsshim/pkg/go-runhcs/runhcs.go
generated
vendored
@@ -5,6 +5,7 @@ package runhcs
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -36,6 +37,11 @@ func getCommandPath() string {
|
||||
pathi := runhcsPath.Load()
|
||||
if pathi == nil {
|
||||
path, err := exec.LookPath(command)
|
||||
if err != nil {
|
||||
if errors.Is(err, exec.ErrDot) {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
// LookPath only finds current directory matches based on the
|
||||
// callers current directory but the caller is not likely in the
|
||||
|
||||
10
vendor/github.com/Microsoft/hcsshim/tools.go
generated
vendored
10
vendor/github.com/Microsoft/hcsshim/tools.go
generated
vendored
@@ -2,4 +2,12 @@
|
||||
|
||||
package hcsshim
|
||||
|
||||
import _ "github.com/Microsoft/go-winio/tools/mkwinsyscall"
|
||||
import (
|
||||
// for go generate directives
|
||||
|
||||
// generate Win32 API code
|
||||
_ "github.com/Microsoft/go-winio/tools/mkwinsyscall"
|
||||
|
||||
// mock gRPC client and servers
|
||||
_ "github.com/golang/mock/mockgen"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user