Update Vendor
(*) github.com/Microsoft/hcsshim (*) golang.org/x/sys (*) github.com/x/cyrpto (*) github.com/sirupsen/logrus (*) github.com/Microsoft/go-winio (*) github.com/juju/errors (*) github.com/buger/jsonparser
This commit is contained in:
431
vendor/github.com/Microsoft/hcsshim/internal/safefile/safeopen.go
generated
vendored
Normal file
431
vendor/github.com/Microsoft/hcsshim/internal/safefile/safeopen.go
generated
vendored
Normal file
@ -0,0 +1,431 @@
|
||||
package safefile
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/longpath"
|
||||
|
||||
winio "github.com/Microsoft/go-winio"
|
||||
)
|
||||
|
||||
//go:generate go run $GOROOT\src\syscall\mksyscall_windows.go -output zsyscall_windows.go safeopen.go
|
||||
|
||||
//sys ntCreateFile(handle *uintptr, accessMask uint32, oa *objectAttributes, iosb *ioStatusBlock, allocationSize *uint64, fileAttributes uint32, shareAccess uint32, createDisposition uint32, createOptions uint32, eaBuffer *byte, eaLength uint32) (status uint32) = ntdll.NtCreateFile
|
||||
//sys ntSetInformationFile(handle uintptr, iosb *ioStatusBlock, information uintptr, length uint32, class uint32) (status uint32) = ntdll.NtSetInformationFile
|
||||
//sys rtlNtStatusToDosError(status uint32) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||
//sys localAlloc(flags uint32, size int) (ptr uintptr) = kernel32.LocalAlloc
|
||||
//sys localFree(ptr uintptr) = kernel32.LocalFree
|
||||
|
||||
type ioStatusBlock struct {
|
||||
Status, Information uintptr
|
||||
}
|
||||
|
||||
type objectAttributes struct {
|
||||
Length uintptr
|
||||
RootDirectory uintptr
|
||||
ObjectName uintptr
|
||||
Attributes uintptr
|
||||
SecurityDescriptor uintptr
|
||||
SecurityQoS uintptr
|
||||
}
|
||||
|
||||
type unicodeString struct {
|
||||
Length uint16
|
||||
MaximumLength uint16
|
||||
Buffer uintptr
|
||||
}
|
||||
|
||||
type fileLinkInformation struct {
|
||||
ReplaceIfExists bool
|
||||
RootDirectory uintptr
|
||||
FileNameLength uint32
|
||||
FileName [1]uint16
|
||||
}
|
||||
|
||||
type fileDispositionInformationEx struct {
|
||||
Flags uintptr
|
||||
}
|
||||
|
||||
const (
|
||||
_FileLinkInformation = 11
|
||||
_FileDispositionInformationEx = 64
|
||||
|
||||
FILE_READ_ATTRIBUTES = 0x0080
|
||||
FILE_WRITE_ATTRIBUTES = 0x0100
|
||||
DELETE = 0x10000
|
||||
|
||||
FILE_OPEN = 1
|
||||
FILE_CREATE = 2
|
||||
|
||||
FILE_DIRECTORY_FILE = 0x00000001
|
||||
FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020
|
||||
FILE_DELETE_ON_CLOSE = 0x00001000
|
||||
FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000
|
||||
FILE_OPEN_REPARSE_POINT = 0x00200000
|
||||
|
||||
FILE_DISPOSITION_DELETE = 0x00000001
|
||||
|
||||
_OBJ_DONT_REPARSE = 0x1000
|
||||
|
||||
_STATUS_REPARSE_POINT_ENCOUNTERED = 0xC000050B
|
||||
)
|
||||
|
||||
func OpenRoot(path string) (*os.File, error) {
|
||||
longpath, err := longpath.LongAbs(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return winio.OpenForBackup(longpath, syscall.GENERIC_READ, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, syscall.OPEN_EXISTING)
|
||||
}
|
||||
|
||||
func ntRelativePath(path string) ([]uint16, error) {
|
||||
path = filepath.Clean(path)
|
||||
if strings.Contains(":", path) {
|
||||
// Since alternate data streams must follow the file they
|
||||
// are attached to, finding one here (out of order) is invalid.
|
||||
return nil, errors.New("path contains invalid character `:`")
|
||||
}
|
||||
fspath := filepath.FromSlash(path)
|
||||
if len(fspath) > 0 && fspath[0] == '\\' {
|
||||
return nil, errors.New("expected relative path")
|
||||
}
|
||||
|
||||
path16 := utf16.Encode(([]rune)(fspath))
|
||||
if len(path16) > 32767 {
|
||||
return nil, syscall.ENAMETOOLONG
|
||||
}
|
||||
|
||||
return path16, nil
|
||||
}
|
||||
|
||||
// openRelativeInternal opens a relative path from the given root, failing if
|
||||
// any of the intermediate path components are reparse points.
|
||||
func openRelativeInternal(path string, root *os.File, accessMask uint32, shareFlags uint32, createDisposition uint32, flags uint32) (*os.File, error) {
|
||||
var (
|
||||
h uintptr
|
||||
iosb ioStatusBlock
|
||||
oa objectAttributes
|
||||
)
|
||||
|
||||
path16, err := ntRelativePath(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if root == nil || root.Fd() == 0 {
|
||||
return nil, errors.New("missing root directory")
|
||||
}
|
||||
|
||||
upathBuffer := localAlloc(0, int(unsafe.Sizeof(unicodeString{}))+len(path16)*2)
|
||||
defer localFree(upathBuffer)
|
||||
|
||||
upath := (*unicodeString)(unsafe.Pointer(upathBuffer))
|
||||
upath.Length = uint16(len(path16) * 2)
|
||||
upath.MaximumLength = upath.Length
|
||||
upath.Buffer = upathBuffer + unsafe.Sizeof(*upath)
|
||||
copy((*[32768]uint16)(unsafe.Pointer(upath.Buffer))[:], path16)
|
||||
|
||||
oa.Length = unsafe.Sizeof(oa)
|
||||
oa.ObjectName = upathBuffer
|
||||
oa.RootDirectory = uintptr(root.Fd())
|
||||
oa.Attributes = _OBJ_DONT_REPARSE
|
||||
status := ntCreateFile(
|
||||
&h,
|
||||
accessMask|syscall.SYNCHRONIZE,
|
||||
&oa,
|
||||
&iosb,
|
||||
nil,
|
||||
0,
|
||||
shareFlags,
|
||||
createDisposition,
|
||||
FILE_OPEN_FOR_BACKUP_INTENT|FILE_SYNCHRONOUS_IO_NONALERT|flags,
|
||||
nil,
|
||||
0,
|
||||
)
|
||||
if status != 0 {
|
||||
return nil, rtlNtStatusToDosError(status)
|
||||
}
|
||||
|
||||
fullPath, err := longpath.LongAbs(filepath.Join(root.Name(), path))
|
||||
if err != nil {
|
||||
syscall.Close(syscall.Handle(h))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return os.NewFile(h, fullPath), nil
|
||||
}
|
||||
|
||||
// OpenRelative opens a relative path from the given root, failing if
|
||||
// any of the intermediate path components are reparse points.
|
||||
func OpenRelative(path string, root *os.File, accessMask uint32, shareFlags uint32, createDisposition uint32, flags uint32) (*os.File, error) {
|
||||
f, err := openRelativeInternal(path, root, accessMask, shareFlags, createDisposition, flags)
|
||||
if err != nil {
|
||||
err = &os.PathError{Op: "open", Path: filepath.Join(root.Name(), path), Err: err}
|
||||
}
|
||||
return f, err
|
||||
}
|
||||
|
||||
// LinkRelative creates a hard link from oldname to newname (relative to oldroot
|
||||
// and newroot), failing if any of the intermediate path components are reparse
|
||||
// points.
|
||||
func LinkRelative(oldname string, oldroot *os.File, newname string, newroot *os.File) error {
|
||||
// Open the old file.
|
||||
oldf, err := openRelativeInternal(
|
||||
oldname,
|
||||
oldroot,
|
||||
syscall.FILE_WRITE_ATTRIBUTES,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return &os.LinkError{Op: "link", Old: filepath.Join(oldroot.Name(), oldname), New: filepath.Join(newroot.Name(), newname), Err: err}
|
||||
}
|
||||
defer oldf.Close()
|
||||
|
||||
// Open the parent of the new file.
|
||||
var parent *os.File
|
||||
parentPath := filepath.Dir(newname)
|
||||
if parentPath != "." {
|
||||
parent, err = openRelativeInternal(
|
||||
parentPath,
|
||||
newroot,
|
||||
syscall.GENERIC_READ,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
FILE_DIRECTORY_FILE)
|
||||
if err != nil {
|
||||
return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(newroot.Name(), newname), Err: err}
|
||||
}
|
||||
defer parent.Close()
|
||||
|
||||
fi, err := winio.GetFileBasicInfo(parent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (fi.FileAttributes & syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 {
|
||||
return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(newroot.Name(), newname), Err: rtlNtStatusToDosError(_STATUS_REPARSE_POINT_ENCOUNTERED)}
|
||||
}
|
||||
|
||||
} else {
|
||||
parent = newroot
|
||||
}
|
||||
|
||||
// Issue an NT call to create the link. This will be safe because NT will
|
||||
// not open any more directories to create the link, so it cannot walk any
|
||||
// more reparse points.
|
||||
newbase := filepath.Base(newname)
|
||||
newbase16, err := ntRelativePath(newbase)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
size := int(unsafe.Offsetof(fileLinkInformation{}.FileName)) + len(newbase16)*2
|
||||
linkinfoBuffer := localAlloc(0, size)
|
||||
defer localFree(linkinfoBuffer)
|
||||
linkinfo := (*fileLinkInformation)(unsafe.Pointer(linkinfoBuffer))
|
||||
linkinfo.RootDirectory = parent.Fd()
|
||||
linkinfo.FileNameLength = uint32(len(newbase16) * 2)
|
||||
copy((*[32768]uint16)(unsafe.Pointer(&linkinfo.FileName[0]))[:], newbase16)
|
||||
|
||||
var iosb ioStatusBlock
|
||||
status := ntSetInformationFile(
|
||||
oldf.Fd(),
|
||||
&iosb,
|
||||
linkinfoBuffer,
|
||||
uint32(size),
|
||||
_FileLinkInformation,
|
||||
)
|
||||
if status != 0 {
|
||||
return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(parent.Name(), newbase), Err: rtlNtStatusToDosError(status)}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// deleteOnClose marks a file to be deleted when the handle is closed.
|
||||
func deleteOnClose(f *os.File) error {
|
||||
disposition := fileDispositionInformationEx{Flags: FILE_DISPOSITION_DELETE}
|
||||
var iosb ioStatusBlock
|
||||
status := ntSetInformationFile(
|
||||
f.Fd(),
|
||||
&iosb,
|
||||
uintptr(unsafe.Pointer(&disposition)),
|
||||
uint32(unsafe.Sizeof(disposition)),
|
||||
_FileDispositionInformationEx,
|
||||
)
|
||||
if status != 0 {
|
||||
return rtlNtStatusToDosError(status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// clearReadOnly clears the readonly attribute on a file.
|
||||
func clearReadOnly(f *os.File) error {
|
||||
bi, err := winio.GetFileBasicInfo(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if bi.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY == 0 {
|
||||
return nil
|
||||
}
|
||||
sbi := winio.FileBasicInfo{
|
||||
FileAttributes: bi.FileAttributes &^ syscall.FILE_ATTRIBUTE_READONLY,
|
||||
}
|
||||
if sbi.FileAttributes == 0 {
|
||||
sbi.FileAttributes = syscall.FILE_ATTRIBUTE_NORMAL
|
||||
}
|
||||
return winio.SetFileBasicInfo(f, &sbi)
|
||||
}
|
||||
|
||||
// RemoveRelative removes a file or directory relative to a root, failing if any
|
||||
// intermediate path components are reparse points.
|
||||
func RemoveRelative(path string, root *os.File) error {
|
||||
f, err := openRelativeInternal(
|
||||
path,
|
||||
root,
|
||||
FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES|DELETE,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
FILE_OPEN_REPARSE_POINT)
|
||||
if err == nil {
|
||||
defer f.Close()
|
||||
err = deleteOnClose(f)
|
||||
if err == syscall.ERROR_ACCESS_DENIED {
|
||||
// Maybe the file is marked readonly. Clear the bit and retry.
|
||||
clearReadOnly(f)
|
||||
err = deleteOnClose(f)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return &os.PathError{Op: "remove", Path: filepath.Join(root.Name(), path), Err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveAllRelative removes a directory tree relative to a root, failing if any
|
||||
// intermediate path components are reparse points.
|
||||
func RemoveAllRelative(path string, root *os.File) error {
|
||||
fi, err := LstatRelative(path, root)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
fileAttributes := fi.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
||||
if fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY == 0 || fileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 {
|
||||
// If this is a reparse point, it can't have children. Simple remove will do.
|
||||
err := RemoveRelative(path, root)
|
||||
if err == nil || os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// It is necessary to use os.Open as Readdirnames does not work with
|
||||
// OpenRelative. This is safe because the above lstatrelative fails
|
||||
// if the target is outside the root, and we know this is not a
|
||||
// symlink from the above FILE_ATTRIBUTE_REPARSE_POINT check.
|
||||
fd, err := os.Open(filepath.Join(root.Name(), path))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// Race. It was deleted between the Lstat and Open.
|
||||
// Return nil per RemoveAll's docs.
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove contents & return first error.
|
||||
for {
|
||||
names, err1 := fd.Readdirnames(100)
|
||||
for _, name := range names {
|
||||
err1 := RemoveAllRelative(path+string(os.PathSeparator)+name, root)
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
}
|
||||
if err1 == io.EOF {
|
||||
break
|
||||
}
|
||||
// If Readdirnames returned an error, use it.
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
if len(names) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fd.Close()
|
||||
|
||||
// Remove directory.
|
||||
err1 := RemoveRelative(path, root)
|
||||
if err1 == nil || os.IsNotExist(err1) {
|
||||
return nil
|
||||
}
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// MkdirRelative creates a directory relative to a root, failing if any
|
||||
// intermediate path components are reparse points.
|
||||
func MkdirRelative(path string, root *os.File) error {
|
||||
f, err := openRelativeInternal(
|
||||
path,
|
||||
root,
|
||||
0,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||
FILE_CREATE,
|
||||
FILE_DIRECTORY_FILE)
|
||||
if err == nil {
|
||||
f.Close()
|
||||
} else {
|
||||
err = &os.PathError{Op: "mkdir", Path: filepath.Join(root.Name(), path), Err: err}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// LstatRelative performs a stat operation on a file relative to a root, failing
|
||||
// if any intermediate path components are reparse points.
|
||||
func LstatRelative(path string, root *os.File) (os.FileInfo, error) {
|
||||
f, err := openRelativeInternal(
|
||||
path,
|
||||
root,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
FILE_OPEN_REPARSE_POINT)
|
||||
if err != nil {
|
||||
return nil, &os.PathError{Op: "stat", Path: filepath.Join(root.Name(), path), Err: err}
|
||||
}
|
||||
defer f.Close()
|
||||
return f.Stat()
|
||||
}
|
||||
|
||||
// EnsureNotReparsePointRelative validates that a given file (relative to a
|
||||
// root) and all intermediate path components are not a reparse points.
|
||||
func EnsureNotReparsePointRelative(path string, root *os.File) error {
|
||||
// Perform an open with OBJ_DONT_REPARSE but without specifying FILE_OPEN_REPARSE_POINT.
|
||||
f, err := OpenRelative(
|
||||
path,
|
||||
root,
|
||||
0,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.Close()
|
||||
return nil
|
||||
}
|
79
vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go
generated
vendored
Normal file
79
vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
// Code generated by 'go generate'; DO NOT EDIT.
|
||||
|
||||
package safefile
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
// allocations at runtime.
|
||||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return nil
|
||||
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 (
|
||||
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
|
||||
procNtCreateFile = modntdll.NewProc("NtCreateFile")
|
||||
procNtSetInformationFile = modntdll.NewProc("NtSetInformationFile")
|
||||
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
|
||||
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
|
||||
procLocalFree = modkernel32.NewProc("LocalFree")
|
||||
)
|
||||
|
||||
func ntCreateFile(handle *uintptr, accessMask uint32, oa *objectAttributes, iosb *ioStatusBlock, allocationSize *uint64, fileAttributes uint32, shareAccess uint32, createDisposition uint32, createOptions uint32, eaBuffer *byte, eaLength uint32) (status uint32) {
|
||||
r0, _, _ := syscall.Syscall12(procNtCreateFile.Addr(), 11, uintptr(unsafe.Pointer(handle)), uintptr(accessMask), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(allocationSize)), uintptr(fileAttributes), uintptr(shareAccess), uintptr(createDisposition), uintptr(createOptions), uintptr(unsafe.Pointer(eaBuffer)), uintptr(eaLength), 0)
|
||||
status = uint32(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func ntSetInformationFile(handle uintptr, iosb *ioStatusBlock, information uintptr, length uint32, class uint32) (status uint32) {
|
||||
r0, _, _ := syscall.Syscall6(procNtSetInformationFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(information), uintptr(length), uintptr(class), 0)
|
||||
status = uint32(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlNtStatusToDosError(status uint32) (winerr error) {
|
||||
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
|
||||
if r0 != 0 {
|
||||
winerr = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func localAlloc(flags uint32, size int) (ptr uintptr) {
|
||||
r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(flags), uintptr(size), 0)
|
||||
ptr = uintptr(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func localFree(ptr uintptr) {
|
||||
syscall.Syscall(procLocalFree.Addr(), 1, uintptr(ptr), 0, 0)
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user