Update vendor
Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
parent
50c73e6dc5
commit
86de625ece
@ -25,6 +25,7 @@ github.com/opencontainers/runc f4982d86f7fde0b6f953cc62ccc4022c519a10a9 # v1.0.0
|
|||||||
github.com/opencontainers/image-spec v1.0.1
|
github.com/opencontainers/image-spec v1.0.1
|
||||||
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1
|
github.com/matttproud/golang_protobuf_extensions v1.0.1
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.1
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.1
|
||||||
github.com/google/uuid v1.1.1
|
github.com/google/uuid v1.1.1
|
||||||
github.com/golang/protobuf v1.2.0
|
github.com/golang/protobuf v1.2.0
|
||||||
|
47
vendor/github.com/Microsoft/go-winio/pkg/fs/fs_windows.go
generated
vendored
Normal file
47
vendor/github.com/Microsoft/go-winio/pkg/fs/fs_windows.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrInvalidPath is returned when the location of a file path doesn't begin with a driver letter.
|
||||||
|
ErrInvalidPath = errors.New("the path provided to GetFileSystemType must start with a drive letter")
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetFileSystemType obtains the type of a file system through GetVolumeInformation.
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx
|
||||||
|
func GetFileSystemType(path string) (fsType string, hr error) {
|
||||||
|
drive := filepath.VolumeName(path)
|
||||||
|
if len(drive) != 2 {
|
||||||
|
return "", ErrInvalidPath
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
|
procGetVolumeInformation = modkernel32.NewProc("GetVolumeInformationW")
|
||||||
|
buf = make([]uint16, 255)
|
||||||
|
size = windows.MAX_PATH + 1
|
||||||
|
)
|
||||||
|
drive += `\`
|
||||||
|
n := uintptr(unsafe.Pointer(nil))
|
||||||
|
r0, _, _ := syscall.Syscall9(procGetVolumeInformation.Addr(), 8, uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(drive))), n, n, n, n, n, uintptr(unsafe.Pointer(&buf[0])), uintptr(size), 0)
|
||||||
|
if int32(r0) < 0 {
|
||||||
|
hr = syscall.Errno(win32FromHresult(r0))
|
||||||
|
}
|
||||||
|
fsType = windows.UTF16ToString(buf)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// win32FromHresult is a helper function to get the win32 error code from an HRESULT.
|
||||||
|
func win32FromHresult(hr uintptr) uintptr {
|
||||||
|
if hr&0x1fff0000 == 0x00070000 {
|
||||||
|
return hr & 0xffff
|
||||||
|
}
|
||||||
|
return hr
|
||||||
|
}
|
159
vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go
generated
vendored
Normal file
159
vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go
generated
vendored
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
package security
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
accessMask uint32
|
||||||
|
accessMode uint32
|
||||||
|
desiredAccess uint32
|
||||||
|
inheritMode uint32
|
||||||
|
objectType uint32
|
||||||
|
shareMode uint32
|
||||||
|
securityInformation uint32
|
||||||
|
trusteeForm uint32
|
||||||
|
trusteeType uint32
|
||||||
|
|
||||||
|
explicitAccess struct {
|
||||||
|
accessPermissions accessMask
|
||||||
|
accessMode accessMode
|
||||||
|
inheritance inheritMode
|
||||||
|
trustee trustee
|
||||||
|
}
|
||||||
|
|
||||||
|
trustee struct {
|
||||||
|
multipleTrustee *trustee
|
||||||
|
multipleTrusteeOperation int32
|
||||||
|
trusteeForm trusteeForm
|
||||||
|
trusteeType trusteeType
|
||||||
|
name uintptr
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
accessMaskDesiredPermission accessMask = 1 << 31 // GENERIC_READ
|
||||||
|
|
||||||
|
accessModeGrant accessMode = 1
|
||||||
|
|
||||||
|
desiredAccessReadControl desiredAccess = 0x20000
|
||||||
|
desiredAccessWriteDac desiredAccess = 0x40000
|
||||||
|
|
||||||
|
gvmga = "GrantVmGroupAccess:"
|
||||||
|
|
||||||
|
inheritModeNoInheritance inheritMode = 0x0
|
||||||
|
inheritModeSubContainersAndObjectsInherit inheritMode = 0x3
|
||||||
|
|
||||||
|
objectTypeFileObject objectType = 0x1
|
||||||
|
|
||||||
|
securityInformationDACL securityInformation = 0x4
|
||||||
|
|
||||||
|
shareModeRead shareMode = 0x1
|
||||||
|
shareModeWrite shareMode = 0x2
|
||||||
|
|
||||||
|
sidVmGroup = "S-1-5-83-0"
|
||||||
|
|
||||||
|
trusteeFormIsSid trusteeForm = 0
|
||||||
|
|
||||||
|
trusteeTypeWellKnownGroup trusteeType = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
// GrantVMGroupAccess sets the DACL for a specified file or directory to
|
||||||
|
// include Grant ACE entries for the VM Group SID. This is a golang re-
|
||||||
|
// implementation of the same function in vmcompute, just not exported in
|
||||||
|
// RS5. Which kind of sucks. Sucks a lot :/
|
||||||
|
func GrantVmGroupAccess(name string) error {
|
||||||
|
// Stat (to determine if `name` is a directory).
|
||||||
|
s, err := os.Stat(name)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "%s os.Stat %s", gvmga, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a handle to the file/directory. Must defer Close on success.
|
||||||
|
fd, err := createFile(name, s.IsDir())
|
||||||
|
if err != nil {
|
||||||
|
return err // Already wrapped
|
||||||
|
}
|
||||||
|
defer syscall.CloseHandle(fd)
|
||||||
|
|
||||||
|
// Get the current DACL and Security Descriptor. Must defer LocalFree on success.
|
||||||
|
ot := objectTypeFileObject
|
||||||
|
si := securityInformationDACL
|
||||||
|
sd := uintptr(0)
|
||||||
|
origDACL := uintptr(0)
|
||||||
|
if err := getSecurityInfo(fd, uint32(ot), uint32(si), nil, nil, &origDACL, nil, &sd); err != nil {
|
||||||
|
return errors.Wrapf(err, "%s GetSecurityInfo %s", gvmga, name)
|
||||||
|
}
|
||||||
|
defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd)))
|
||||||
|
|
||||||
|
// Generate a new DACL which is the current DACL with the required ACEs added.
|
||||||
|
// Must defer LocalFree on success.
|
||||||
|
newDACL, err := generateDACLWithAcesAdded(name, s.IsDir(), origDACL)
|
||||||
|
if err != nil {
|
||||||
|
return err // Already wrapped
|
||||||
|
}
|
||||||
|
defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL)))
|
||||||
|
|
||||||
|
// And finally use SetSecurityInfo to apply the updated DACL.
|
||||||
|
if err := setSecurityInfo(fd, uint32(ot), uint32(si), uintptr(0), uintptr(0), newDACL, uintptr(0)); err != nil {
|
||||||
|
return errors.Wrapf(err, "%s SetSecurityInfo %s", gvmga, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createFile is a helper function to call [Nt]CreateFile to get a handle to
|
||||||
|
// the file or directory.
|
||||||
|
func createFile(name string, isDir bool) (syscall.Handle, error) {
|
||||||
|
namep := syscall.StringToUTF16(name)
|
||||||
|
da := uint32(desiredAccessReadControl | desiredAccessWriteDac)
|
||||||
|
sm := uint32(shareModeRead | shareModeWrite)
|
||||||
|
fa := uint32(syscall.FILE_ATTRIBUTE_NORMAL)
|
||||||
|
if isDir {
|
||||||
|
fa = uint32(fa | syscall.FILE_FLAG_BACKUP_SEMANTICS)
|
||||||
|
}
|
||||||
|
fd, err := syscall.CreateFile(&namep[0], da, sm, nil, syscall.OPEN_EXISTING, fa, 0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.Wrapf(err, "%s syscall.CreateFile %s", gvmga, name)
|
||||||
|
}
|
||||||
|
return fd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateDACLWithAcesAdded generates a new DACL with the two needed ACEs added.
|
||||||
|
// The caller is responsible for LocalFree of the returned DACL on success.
|
||||||
|
func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintptr, error) {
|
||||||
|
// Generate pointers to the SIDs based on the string SIDs
|
||||||
|
sid, err := syscall.StringToSid(sidVmGroup)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.Wrapf(err, "%s syscall.StringToSid %s %s", gvmga, name, sidVmGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
inheritance := inheritModeNoInheritance
|
||||||
|
if isDir {
|
||||||
|
inheritance = inheritModeSubContainersAndObjectsInherit
|
||||||
|
}
|
||||||
|
|
||||||
|
eaArray := []explicitAccess{
|
||||||
|
explicitAccess{
|
||||||
|
accessPermissions: accessMaskDesiredPermission,
|
||||||
|
accessMode: accessModeGrant,
|
||||||
|
inheritance: inheritance,
|
||||||
|
trustee: trustee{
|
||||||
|
trusteeForm: trusteeFormIsSid,
|
||||||
|
trusteeType: trusteeTypeWellKnownGroup,
|
||||||
|
name: uintptr(unsafe.Pointer(sid)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
modifiedDACL := uintptr(0)
|
||||||
|
if err := setEntriesInAcl(uintptr(uint32(1)), uintptr(unsafe.Pointer(&eaArray[0])), origDACL, &modifiedDACL); err != nil {
|
||||||
|
return 0, errors.Wrapf(err, "%s SetEntriesInAcl %s", gvmga, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifiedDACL, nil
|
||||||
|
}
|
7
vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go
generated
vendored
Normal file
7
vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package security
|
||||||
|
|
||||||
|
//go:generate go run mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go
|
||||||
|
|
||||||
|
//sys getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo
|
||||||
|
//sys setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) [failretval!=0] = advapi32.SetSecurityInfo
|
||||||
|
//sys setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (err error) [failretval!=0] = advapi32.SetEntriesInAclW
|
81
vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go
generated
vendored
Normal file
81
vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// Code generated mksyscall_windows.exe DO NOT EDIT
|
||||||
|
|
||||||
|
package security
|
||||||
|
|
||||||
|
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 (
|
||||||
|
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||||
|
|
||||||
|
procGetSecurityInfo = modadvapi32.NewProc("GetSecurityInfo")
|
||||||
|
procSetSecurityInfo = modadvapi32.NewProc("SetSecurityInfo")
|
||||||
|
procSetEntriesInAclW = modadvapi32.NewProc("SetEntriesInAclW")
|
||||||
|
)
|
||||||
|
|
||||||
|
func getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(unsafe.Pointer(ppsidOwner)), uintptr(unsafe.Pointer(ppsidGroup)), uintptr(unsafe.Pointer(ppDacl)), uintptr(unsafe.Pointer(ppSacl)), uintptr(unsafe.Pointer(ppSecurityDescriptor)), 0)
|
||||||
|
if r1 != 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(psidOwner), uintptr(psidGroup), uintptr(pDacl), uintptr(pSacl), 0, 0)
|
||||||
|
if r1 != 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(count), uintptr(pListOfEEs), uintptr(oldAcl), uintptr(unsafe.Pointer(newAcl)), 0, 0)
|
||||||
|
if r1 != 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
151
vendor/github.com/Microsoft/go-winio/vhd/vhd.go
generated
vendored
Normal file
151
vendor/github.com/Microsoft/go-winio/vhd/vhd.go
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package vhd
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
//go:generate go run mksyscall_windows.go -output zvhd.go vhd.go
|
||||||
|
|
||||||
|
//sys createVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.CreateVirtualDisk
|
||||||
|
//sys openVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, flags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.OpenVirtualDisk
|
||||||
|
//sys detachVirtualDisk(handle syscall.Handle, flags uint32, providerSpecificFlags uint32) (err error) [failretval != 0] = VirtDisk.DetachVirtualDisk
|
||||||
|
|
||||||
|
type virtualStorageType struct {
|
||||||
|
DeviceID uint32
|
||||||
|
VendorID [16]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
createVirtualDiskFlag uint32
|
||||||
|
VirtualDiskAccessMask uint32
|
||||||
|
VirtualDiskFlag uint32
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Flags for creating a VHD (not exported)
|
||||||
|
createVirtualDiskFlagNone createVirtualDiskFlag = 0
|
||||||
|
createVirtualDiskFlagFullPhysicalAllocation createVirtualDiskFlag = 1
|
||||||
|
createVirtualDiskFlagPreventWritesToSourceDisk createVirtualDiskFlag = 2
|
||||||
|
createVirtualDiskFlagDoNotCopyMetadataFromParent createVirtualDiskFlag = 4
|
||||||
|
|
||||||
|
// Access Mask for opening a VHD
|
||||||
|
VirtualDiskAccessNone VirtualDiskAccessMask = 0
|
||||||
|
VirtualDiskAccessAttachRO VirtualDiskAccessMask = 65536
|
||||||
|
VirtualDiskAccessAttachRW VirtualDiskAccessMask = 131072
|
||||||
|
VirtualDiskAccessDetach VirtualDiskAccessMask = 262144
|
||||||
|
VirtualDiskAccessGetInfo VirtualDiskAccessMask = 524288
|
||||||
|
VirtualDiskAccessCreate VirtualDiskAccessMask = 1048576
|
||||||
|
VirtualDiskAccessMetaOps VirtualDiskAccessMask = 2097152
|
||||||
|
VirtualDiskAccessRead VirtualDiskAccessMask = 851968
|
||||||
|
VirtualDiskAccessAll VirtualDiskAccessMask = 4128768
|
||||||
|
VirtualDiskAccessWritable VirtualDiskAccessMask = 3276800
|
||||||
|
|
||||||
|
// Flags for opening a VHD
|
||||||
|
OpenVirtualDiskFlagNone VirtualDiskFlag = 0
|
||||||
|
OpenVirtualDiskFlagNoParents VirtualDiskFlag = 0x1
|
||||||
|
OpenVirtualDiskFlagBlankFile VirtualDiskFlag = 0x2
|
||||||
|
OpenVirtualDiskFlagBootDrive VirtualDiskFlag = 0x4
|
||||||
|
OpenVirtualDiskFlagCachedIO VirtualDiskFlag = 0x8
|
||||||
|
OpenVirtualDiskFlagCustomDiffChain VirtualDiskFlag = 0x10
|
||||||
|
OpenVirtualDiskFlagParentCachedIO VirtualDiskFlag = 0x20
|
||||||
|
OpenVirtualDiskFlagVhdSetFileOnly VirtualDiskFlag = 0x40
|
||||||
|
OpenVirtualDiskFlagIgnoreRelativeParentLocator VirtualDiskFlag = 0x80
|
||||||
|
OpenVirtualDiskFlagNoWriteHardening VirtualDiskFlag = 0x100
|
||||||
|
)
|
||||||
|
|
||||||
|
type createVersion2 struct {
|
||||||
|
UniqueID [16]byte // GUID
|
||||||
|
MaximumSize uint64
|
||||||
|
BlockSizeInBytes uint32
|
||||||
|
SectorSizeInBytes uint32
|
||||||
|
ParentPath *uint16 // string
|
||||||
|
SourcePath *uint16 // string
|
||||||
|
OpenFlags uint32
|
||||||
|
ParentVirtualStorageType virtualStorageType
|
||||||
|
SourceVirtualStorageType virtualStorageType
|
||||||
|
ResiliencyGUID [16]byte // GUID
|
||||||
|
}
|
||||||
|
|
||||||
|
type createVirtualDiskParameters struct {
|
||||||
|
Version uint32 // Must always be set to 2
|
||||||
|
Version2 createVersion2
|
||||||
|
}
|
||||||
|
|
||||||
|
type openVersion2 struct {
|
||||||
|
GetInfoOnly int32 // bool but 4-byte aligned
|
||||||
|
ReadOnly int32 // bool but 4-byte aligned
|
||||||
|
ResiliencyGUID [16]byte // GUID
|
||||||
|
}
|
||||||
|
|
||||||
|
type openVirtualDiskParameters struct {
|
||||||
|
Version uint32 // Must always be set to 2
|
||||||
|
Version2 openVersion2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateVhdx will create a simple vhdx file at the given path using default values.
|
||||||
|
func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error {
|
||||||
|
var (
|
||||||
|
defaultType virtualStorageType
|
||||||
|
handle syscall.Handle
|
||||||
|
)
|
||||||
|
|
||||||
|
parameters := createVirtualDiskParameters{
|
||||||
|
Version: 2,
|
||||||
|
Version2: createVersion2{
|
||||||
|
MaximumSize: uint64(maxSizeInGb) * 1024 * 1024 * 1024,
|
||||||
|
BlockSizeInBytes: blockSizeInMb * 1024 * 1024,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := createVirtualDisk(
|
||||||
|
&defaultType,
|
||||||
|
path,
|
||||||
|
uint32(VirtualDiskAccessNone),
|
||||||
|
nil,
|
||||||
|
uint32(createVirtualDiskFlagNone),
|
||||||
|
0,
|
||||||
|
¶meters,
|
||||||
|
nil,
|
||||||
|
&handle); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := syscall.CloseHandle(handle); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DetachVhd detaches a mounted container layer vhd found at `path`.
|
||||||
|
func DetachVhd(path string) error {
|
||||||
|
handle, err := OpenVirtualDisk(
|
||||||
|
path,
|
||||||
|
VirtualDiskAccessNone,
|
||||||
|
OpenVirtualDiskFlagCachedIO|OpenVirtualDiskFlagIgnoreRelativeParentLocator)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer syscall.CloseHandle(handle)
|
||||||
|
return detachVirtualDisk(handle, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenVirtualDisk obtains a handle to a VHD opened with supplied access mask and flags.
|
||||||
|
func OpenVirtualDisk(path string, accessMask VirtualDiskAccessMask, flag VirtualDiskFlag) (syscall.Handle, error) {
|
||||||
|
var (
|
||||||
|
defaultType virtualStorageType
|
||||||
|
handle syscall.Handle
|
||||||
|
)
|
||||||
|
parameters := openVirtualDiskParameters{Version: 2}
|
||||||
|
if err := openVirtualDisk(
|
||||||
|
&defaultType,
|
||||||
|
path,
|
||||||
|
uint32(accessMask),
|
||||||
|
uint32(flag),
|
||||||
|
¶meters,
|
||||||
|
&handle); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return handle, nil
|
||||||
|
}
|
99
vendor/github.com/Microsoft/go-winio/vhd/zvhd.go
generated
vendored
Normal file
99
vendor/github.com/Microsoft/go-winio/vhd/zvhd.go
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
||||||
|
|
||||||
|
package vhd
|
||||||
|
|
||||||
|
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 (
|
||||||
|
modVirtDisk = windows.NewLazySystemDLL("VirtDisk.dll")
|
||||||
|
|
||||||
|
procCreateVirtualDisk = modVirtDisk.NewProc("CreateVirtualDisk")
|
||||||
|
procOpenVirtualDisk = modVirtDisk.NewProc("OpenVirtualDisk")
|
||||||
|
procDetachVirtualDisk = modVirtDisk.NewProc("DetachVirtualDisk")
|
||||||
|
)
|
||||||
|
|
||||||
|
func createVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, err = syscall.UTF16PtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _createVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, securityDescriptor, flags, providerSpecificFlags, parameters, o, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _createVirtualDisk(virtualStorageType *virtualStorageType, path *uint16, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall9(procCreateVirtualDisk.Addr(), 9, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(flags), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(handle)))
|
||||||
|
if r1 != 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func openVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, flags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (err error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, err = syscall.UTF16PtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, flags, parameters, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _openVirtualDisk(virtualStorageType *virtualStorageType, path *uint16, virtualDiskAccessMask uint32, flags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(flags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle)))
|
||||||
|
if r1 != 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func detachVirtualDisk(handle syscall.Handle, flags uint32, providerSpecificFlags uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall(procDetachVirtualDisk.Addr(), 3, uintptr(handle), uintptr(flags), uintptr(providerSpecificFlags))
|
||||||
|
if r1 != 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
1263
vendor/github.com/Microsoft/hcsshim/ext4/internal/compactext4/compact.go
generated
vendored
Normal file
1263
vendor/github.com/Microsoft/hcsshim/ext4/internal/compactext4/compact.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
411
vendor/github.com/Microsoft/hcsshim/ext4/internal/format/format.go
generated
vendored
Normal file
411
vendor/github.com/Microsoft/hcsshim/ext4/internal/format/format.go
generated
vendored
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
package format
|
||||||
|
|
||||||
|
type SuperBlock struct {
|
||||||
|
InodesCount uint32
|
||||||
|
BlocksCountLow uint32
|
||||||
|
RootBlocksCountLow uint32
|
||||||
|
FreeBlocksCountLow uint32
|
||||||
|
FreeInodesCount uint32
|
||||||
|
FirstDataBlock uint32
|
||||||
|
LogBlockSize uint32
|
||||||
|
LogClusterSize uint32
|
||||||
|
BlocksPerGroup uint32
|
||||||
|
ClustersPerGroup uint32
|
||||||
|
InodesPerGroup uint32
|
||||||
|
Mtime uint32
|
||||||
|
Wtime uint32
|
||||||
|
MountCount uint16
|
||||||
|
MaxMountCount uint16
|
||||||
|
Magic uint16
|
||||||
|
State uint16
|
||||||
|
Errors uint16
|
||||||
|
MinorRevisionLevel uint16
|
||||||
|
LastCheck uint32
|
||||||
|
CheckInterval uint32
|
||||||
|
CreatorOS uint32
|
||||||
|
RevisionLevel uint32
|
||||||
|
DefaultReservedUid uint16
|
||||||
|
DefaultReservedGid uint16
|
||||||
|
FirstInode uint32
|
||||||
|
InodeSize uint16
|
||||||
|
BlockGroupNr uint16
|
||||||
|
FeatureCompat CompatFeature
|
||||||
|
FeatureIncompat IncompatFeature
|
||||||
|
FeatureRoCompat RoCompatFeature
|
||||||
|
UUID [16]uint8
|
||||||
|
VolumeName [16]byte
|
||||||
|
LastMounted [64]byte
|
||||||
|
AlgorithmUsageBitmap uint32
|
||||||
|
PreallocBlocks uint8
|
||||||
|
PreallocDirBlocks uint8
|
||||||
|
ReservedGdtBlocks uint16
|
||||||
|
JournalUUID [16]uint8
|
||||||
|
JournalInum uint32
|
||||||
|
JournalDev uint32
|
||||||
|
LastOrphan uint32
|
||||||
|
HashSeed [4]uint32
|
||||||
|
DefHashVersion uint8
|
||||||
|
JournalBackupType uint8
|
||||||
|
DescSize uint16
|
||||||
|
DefaultMountOpts uint32
|
||||||
|
FirstMetaBg uint32
|
||||||
|
MkfsTime uint32
|
||||||
|
JournalBlocks [17]uint32
|
||||||
|
BlocksCountHigh uint32
|
||||||
|
RBlocksCountHigh uint32
|
||||||
|
FreeBlocksCountHigh uint32
|
||||||
|
MinExtraIsize uint16
|
||||||
|
WantExtraIsize uint16
|
||||||
|
Flags uint32
|
||||||
|
RaidStride uint16
|
||||||
|
MmpInterval uint16
|
||||||
|
MmpBlock uint64
|
||||||
|
RaidStripeWidth uint32
|
||||||
|
LogGroupsPerFlex uint8
|
||||||
|
ChecksumType uint8
|
||||||
|
ReservedPad uint16
|
||||||
|
KbytesWritten uint64
|
||||||
|
SnapshotInum uint32
|
||||||
|
SnapshotID uint32
|
||||||
|
SnapshotRBlocksCount uint64
|
||||||
|
SnapshotList uint32
|
||||||
|
ErrorCount uint32
|
||||||
|
FirstErrorTime uint32
|
||||||
|
FirstErrorInode uint32
|
||||||
|
FirstErrorBlock uint64
|
||||||
|
FirstErrorFunc [32]uint8
|
||||||
|
FirstErrorLine uint32
|
||||||
|
LastErrorTime uint32
|
||||||
|
LastErrorInode uint32
|
||||||
|
LastErrorLine uint32
|
||||||
|
LastErrorBlock uint64
|
||||||
|
LastErrorFunc [32]uint8
|
||||||
|
MountOpts [64]uint8
|
||||||
|
UserQuotaInum uint32
|
||||||
|
GroupQuotaInum uint32
|
||||||
|
OverheadBlocks uint32
|
||||||
|
BackupBgs [2]uint32
|
||||||
|
EncryptAlgos [4]uint8
|
||||||
|
EncryptPwSalt [16]uint8
|
||||||
|
LpfInode uint32
|
||||||
|
ProjectQuotaInum uint32
|
||||||
|
ChecksumSeed uint32
|
||||||
|
WtimeHigh uint8
|
||||||
|
MtimeHigh uint8
|
||||||
|
MkfsTimeHigh uint8
|
||||||
|
LastcheckHigh uint8
|
||||||
|
FirstErrorTimeHigh uint8
|
||||||
|
LastErrorTimeHigh uint8
|
||||||
|
Pad [2]uint8
|
||||||
|
Reserved [96]uint32
|
||||||
|
Checksum uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
const SuperBlockMagic uint16 = 0xef53
|
||||||
|
|
||||||
|
type CompatFeature uint32
|
||||||
|
type IncompatFeature uint32
|
||||||
|
type RoCompatFeature uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
CompatDirPrealloc CompatFeature = 0x1
|
||||||
|
CompatImagicInodes CompatFeature = 0x2
|
||||||
|
CompatHasJournal CompatFeature = 0x4
|
||||||
|
CompatExtAttr CompatFeature = 0x8
|
||||||
|
CompatResizeInode CompatFeature = 0x10
|
||||||
|
CompatDirIndex CompatFeature = 0x20
|
||||||
|
CompatLazyBg CompatFeature = 0x40
|
||||||
|
CompatExcludeInode CompatFeature = 0x80
|
||||||
|
CompatExcludeBitmap CompatFeature = 0x100
|
||||||
|
CompatSparseSuper2 CompatFeature = 0x200
|
||||||
|
|
||||||
|
IncompatCompression IncompatFeature = 0x1
|
||||||
|
IncompatFiletype IncompatFeature = 0x2
|
||||||
|
IncompatRecover IncompatFeature = 0x4
|
||||||
|
IncompatJournalDev IncompatFeature = 0x8
|
||||||
|
IncompatMetaBg IncompatFeature = 0x10
|
||||||
|
IncompatExtents IncompatFeature = 0x40
|
||||||
|
Incompat_64Bit IncompatFeature = 0x80
|
||||||
|
IncompatMmp IncompatFeature = 0x100
|
||||||
|
IncompatFlexBg IncompatFeature = 0x200
|
||||||
|
IncompatEaInode IncompatFeature = 0x400
|
||||||
|
IncompatDirdata IncompatFeature = 0x1000
|
||||||
|
IncompatCsumSeed IncompatFeature = 0x2000
|
||||||
|
IncompatLargedir IncompatFeature = 0x4000
|
||||||
|
IncompatInlineData IncompatFeature = 0x8000
|
||||||
|
IncompatEncrypt IncompatFeature = 0x10000
|
||||||
|
|
||||||
|
RoCompatSparseSuper RoCompatFeature = 0x1
|
||||||
|
RoCompatLargeFile RoCompatFeature = 0x2
|
||||||
|
RoCompatBtreeDir RoCompatFeature = 0x4
|
||||||
|
RoCompatHugeFile RoCompatFeature = 0x8
|
||||||
|
RoCompatGdtCsum RoCompatFeature = 0x10
|
||||||
|
RoCompatDirNlink RoCompatFeature = 0x20
|
||||||
|
RoCompatExtraIsize RoCompatFeature = 0x40
|
||||||
|
RoCompatHasSnapshot RoCompatFeature = 0x80
|
||||||
|
RoCompatQuota RoCompatFeature = 0x100
|
||||||
|
RoCompatBigalloc RoCompatFeature = 0x200
|
||||||
|
RoCompatMetadataCsum RoCompatFeature = 0x400
|
||||||
|
RoCompatReplica RoCompatFeature = 0x800
|
||||||
|
RoCompatReadonly RoCompatFeature = 0x1000
|
||||||
|
RoCompatProject RoCompatFeature = 0x2000
|
||||||
|
)
|
||||||
|
|
||||||
|
type BlockGroupFlag uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
BlockGroupInodeUninit BlockGroupFlag = 0x1
|
||||||
|
BlockGroupBlockUninit BlockGroupFlag = 0x2
|
||||||
|
BlockGroupInodeZeroed BlockGroupFlag = 0x4
|
||||||
|
)
|
||||||
|
|
||||||
|
type GroupDescriptor struct {
|
||||||
|
BlockBitmapLow uint32
|
||||||
|
InodeBitmapLow uint32
|
||||||
|
InodeTableLow uint32
|
||||||
|
FreeBlocksCountLow uint16
|
||||||
|
FreeInodesCountLow uint16
|
||||||
|
UsedDirsCountLow uint16
|
||||||
|
Flags BlockGroupFlag
|
||||||
|
ExcludeBitmapLow uint32
|
||||||
|
BlockBitmapCsumLow uint16
|
||||||
|
InodeBitmapCsumLow uint16
|
||||||
|
ItableUnusedLow uint16
|
||||||
|
Checksum uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type GroupDescriptor64 struct {
|
||||||
|
GroupDescriptor
|
||||||
|
BlockBitmapHigh uint32
|
||||||
|
InodeBitmapHigh uint32
|
||||||
|
InodeTableHigh uint32
|
||||||
|
FreeBlocksCountHigh uint16
|
||||||
|
FreeInodesCountHigh uint16
|
||||||
|
UsedDirsCountHigh uint16
|
||||||
|
ItableUnusedHigh uint16
|
||||||
|
ExcludeBitmapHigh uint32
|
||||||
|
BlockBitmapCsumHigh uint16
|
||||||
|
InodeBitmapCsumHigh uint16
|
||||||
|
Reserved uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
S_IXOTH = 0x1
|
||||||
|
S_IWOTH = 0x2
|
||||||
|
S_IROTH = 0x4
|
||||||
|
S_IXGRP = 0x8
|
||||||
|
S_IWGRP = 0x10
|
||||||
|
S_IRGRP = 0x20
|
||||||
|
S_IXUSR = 0x40
|
||||||
|
S_IWUSR = 0x80
|
||||||
|
S_IRUSR = 0x100
|
||||||
|
S_ISVTX = 0x200
|
||||||
|
S_ISGID = 0x400
|
||||||
|
S_ISUID = 0x800
|
||||||
|
S_IFIFO = 0x1000
|
||||||
|
S_IFCHR = 0x2000
|
||||||
|
S_IFDIR = 0x4000
|
||||||
|
S_IFBLK = 0x6000
|
||||||
|
S_IFREG = 0x8000
|
||||||
|
S_IFLNK = 0xA000
|
||||||
|
S_IFSOCK = 0xC000
|
||||||
|
|
||||||
|
TypeMask uint16 = 0xF000
|
||||||
|
)
|
||||||
|
|
||||||
|
type InodeNumber uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
InodeRoot = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type Inode struct {
|
||||||
|
Mode uint16
|
||||||
|
Uid uint16
|
||||||
|
SizeLow uint32
|
||||||
|
Atime uint32
|
||||||
|
Ctime uint32
|
||||||
|
Mtime uint32
|
||||||
|
Dtime uint32
|
||||||
|
Gid uint16
|
||||||
|
LinksCount uint16
|
||||||
|
BlocksLow uint32
|
||||||
|
Flags InodeFlag
|
||||||
|
Version uint32
|
||||||
|
Block [60]byte
|
||||||
|
Generation uint32
|
||||||
|
XattrBlockLow uint32
|
||||||
|
SizeHigh uint32
|
||||||
|
ObsoleteFragmentAddr uint32
|
||||||
|
BlocksHigh uint16
|
||||||
|
XattrBlockHigh uint16
|
||||||
|
UidHigh uint16
|
||||||
|
GidHigh uint16
|
||||||
|
ChecksumLow uint16
|
||||||
|
Reserved uint16
|
||||||
|
ExtraIsize uint16
|
||||||
|
ChecksumHigh uint16
|
||||||
|
CtimeExtra uint32
|
||||||
|
MtimeExtra uint32
|
||||||
|
AtimeExtra uint32
|
||||||
|
Crtime uint32
|
||||||
|
CrtimeExtra uint32
|
||||||
|
VersionHigh uint32
|
||||||
|
Projid uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type InodeFlag uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
InodeFlagSecRm InodeFlag = 0x1
|
||||||
|
InodeFlagUnRm InodeFlag = 0x2
|
||||||
|
InodeFlagCompressed InodeFlag = 0x4
|
||||||
|
InodeFlagSync InodeFlag = 0x8
|
||||||
|
InodeFlagImmutable InodeFlag = 0x10
|
||||||
|
InodeFlagAppend InodeFlag = 0x20
|
||||||
|
InodeFlagNoDump InodeFlag = 0x40
|
||||||
|
InodeFlagNoAtime InodeFlag = 0x80
|
||||||
|
InodeFlagDirtyCompressed InodeFlag = 0x100
|
||||||
|
InodeFlagCompressedClusters InodeFlag = 0x200
|
||||||
|
InodeFlagNoCompress InodeFlag = 0x400
|
||||||
|
InodeFlagEncrypted InodeFlag = 0x800
|
||||||
|
InodeFlagHashedIndex InodeFlag = 0x1000
|
||||||
|
InodeFlagMagic InodeFlag = 0x2000
|
||||||
|
InodeFlagJournalData InodeFlag = 0x4000
|
||||||
|
InodeFlagNoTail InodeFlag = 0x8000
|
||||||
|
InodeFlagDirSync InodeFlag = 0x10000
|
||||||
|
InodeFlagTopDir InodeFlag = 0x20000
|
||||||
|
InodeFlagHugeFile InodeFlag = 0x40000
|
||||||
|
InodeFlagExtents InodeFlag = 0x80000
|
||||||
|
InodeFlagEaInode InodeFlag = 0x200000
|
||||||
|
InodeFlagEOFBlocks InodeFlag = 0x400000
|
||||||
|
InodeFlagSnapfile InodeFlag = 0x01000000
|
||||||
|
InodeFlagSnapfileDeleted InodeFlag = 0x04000000
|
||||||
|
InodeFlagSnapfileShrunk InodeFlag = 0x08000000
|
||||||
|
InodeFlagInlineData InodeFlag = 0x10000000
|
||||||
|
InodeFlagProjectIDInherit InodeFlag = 0x20000000
|
||||||
|
InodeFlagReserved InodeFlag = 0x80000000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MaxLinks = 65000
|
||||||
|
)
|
||||||
|
|
||||||
|
type ExtentHeader struct {
|
||||||
|
Magic uint16
|
||||||
|
Entries uint16
|
||||||
|
Max uint16
|
||||||
|
Depth uint16
|
||||||
|
Generation uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
const ExtentHeaderMagic uint16 = 0xf30a
|
||||||
|
|
||||||
|
type ExtentIndexNode struct {
|
||||||
|
Block uint32
|
||||||
|
LeafLow uint32
|
||||||
|
LeafHigh uint16
|
||||||
|
Unused uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtentLeafNode struct {
|
||||||
|
Block uint32
|
||||||
|
Length uint16
|
||||||
|
StartHigh uint16
|
||||||
|
StartLow uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtentTail struct {
|
||||||
|
Checksum uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type DirectoryEntry struct {
|
||||||
|
Inode InodeNumber
|
||||||
|
RecordLength uint16
|
||||||
|
NameLength uint8
|
||||||
|
FileType FileType
|
||||||
|
//Name []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
FileTypeUnknown FileType = 0x0
|
||||||
|
FileTypeRegular FileType = 0x1
|
||||||
|
FileTypeDirectory FileType = 0x2
|
||||||
|
FileTypeCharacter FileType = 0x3
|
||||||
|
FileTypeBlock FileType = 0x4
|
||||||
|
FileTypeFIFO FileType = 0x5
|
||||||
|
FileTypeSocket FileType = 0x6
|
||||||
|
FileTypeSymbolicLink FileType = 0x7
|
||||||
|
)
|
||||||
|
|
||||||
|
type DirectoryEntryTail struct {
|
||||||
|
ReservedZero1 uint32
|
||||||
|
RecordLength uint16
|
||||||
|
ReservedZero2 uint8
|
||||||
|
FileType uint8
|
||||||
|
Checksum uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type DirectoryTreeRoot struct {
|
||||||
|
Dot DirectoryEntry
|
||||||
|
DotName [4]byte
|
||||||
|
DotDot DirectoryEntry
|
||||||
|
DotDotName [4]byte
|
||||||
|
ReservedZero uint32
|
||||||
|
HashVersion uint8
|
||||||
|
InfoLength uint8
|
||||||
|
IndirectLevels uint8
|
||||||
|
UnusedFlags uint8
|
||||||
|
Limit uint16
|
||||||
|
Count uint16
|
||||||
|
Block uint32
|
||||||
|
//Entries []DirectoryTreeEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
type DirectoryTreeNode struct {
|
||||||
|
FakeInode uint32
|
||||||
|
FakeRecordLength uint16
|
||||||
|
NameLength uint8
|
||||||
|
FileType uint8
|
||||||
|
Limit uint16
|
||||||
|
Count uint16
|
||||||
|
Block uint32
|
||||||
|
//Entries []DirectoryTreeEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
type DirectoryTreeEntry struct {
|
||||||
|
Hash uint32
|
||||||
|
Block uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type DirectoryTreeTail struct {
|
||||||
|
Reserved uint32
|
||||||
|
Checksum uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type XAttrInodeBodyHeader struct {
|
||||||
|
Magic uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type XAttrHeader struct {
|
||||||
|
Magic uint32
|
||||||
|
ReferenceCount uint32
|
||||||
|
Blocks uint32
|
||||||
|
Hash uint32
|
||||||
|
Checksum uint32
|
||||||
|
Reserved [3]uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
const XAttrHeaderMagic uint32 = 0xea020000
|
||||||
|
|
||||||
|
type XAttrEntry struct {
|
||||||
|
NameLength uint8
|
||||||
|
NameIndex uint8
|
||||||
|
ValueOffset uint16
|
||||||
|
ValueInum uint32
|
||||||
|
ValueSize uint32
|
||||||
|
Hash uint32
|
||||||
|
//Name []byte
|
||||||
|
}
|
174
vendor/github.com/Microsoft/hcsshim/ext4/tar2ext4/tar2ext4.go
generated
vendored
Normal file
174
vendor/github.com/Microsoft/hcsshim/ext4/tar2ext4/tar2ext4.go
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
package tar2ext4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"bufio"
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Microsoft/hcsshim/ext4/internal/compactext4"
|
||||||
|
)
|
||||||
|
|
||||||
|
type params struct {
|
||||||
|
convertWhiteout bool
|
||||||
|
appendVhdFooter bool
|
||||||
|
ext4opts []compactext4.Option
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option is the type for optional parameters to Convert.
|
||||||
|
type Option func(*params)
|
||||||
|
|
||||||
|
// ConvertWhiteout instructs the converter to convert OCI-style whiteouts
|
||||||
|
// (beginning with .wh.) to overlay-style whiteouts.
|
||||||
|
func ConvertWhiteout(p *params) {
|
||||||
|
p.convertWhiteout = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendVhdFooter instructs the converter to add a fixed VHD footer to the
|
||||||
|
// file.
|
||||||
|
func AppendVhdFooter(p *params) {
|
||||||
|
p.appendVhdFooter = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// InlineData instructs the converter to write small files into the inode
|
||||||
|
// structures directly. This creates smaller images but currently is not
|
||||||
|
// compatible with DAX.
|
||||||
|
func InlineData(p *params) {
|
||||||
|
p.ext4opts = append(p.ext4opts, compactext4.InlineData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaximumDiskSize instructs the writer to limit the disk size to the specified
|
||||||
|
// value. This also reserves enough metadata space for the specified disk size.
|
||||||
|
// If not provided, then 16GB is the default.
|
||||||
|
func MaximumDiskSize(size int64) Option {
|
||||||
|
return func(p *params) {
|
||||||
|
p.ext4opts = append(p.ext4opts, compactext4.MaximumDiskSize(size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
whiteoutPrefix = ".wh."
|
||||||
|
opaqueWhiteout = ".wh..wh..opq"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Convert writes a compact ext4 file system image that contains the files in the
|
||||||
|
// input tar stream.
|
||||||
|
func Convert(r io.Reader, w io.ReadWriteSeeker, options ...Option) error {
|
||||||
|
var p params
|
||||||
|
for _, opt := range options {
|
||||||
|
opt(&p)
|
||||||
|
}
|
||||||
|
t := tar.NewReader(bufio.NewReader(r))
|
||||||
|
fs := compactext4.NewWriter(w, p.ext4opts...)
|
||||||
|
for {
|
||||||
|
hdr, err := t.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.convertWhiteout {
|
||||||
|
dir, name := path.Split(hdr.Name)
|
||||||
|
if strings.HasPrefix(name, whiteoutPrefix) {
|
||||||
|
if name == opaqueWhiteout {
|
||||||
|
// Update the directory with the appropriate xattr.
|
||||||
|
f, err := fs.Stat(dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.Xattrs["trusted.overlay.opaque"] = []byte("y")
|
||||||
|
err = fs.Create(dir, f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create an overlay-style whiteout.
|
||||||
|
f := &compactext4.File{
|
||||||
|
Mode: compactext4.S_IFCHR,
|
||||||
|
Devmajor: 0,
|
||||||
|
Devminor: 0,
|
||||||
|
}
|
||||||
|
err = fs.Create(path.Join(dir, name[len(whiteoutPrefix):]), f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if hdr.Typeflag == tar.TypeLink {
|
||||||
|
err = fs.Link(hdr.Linkname, hdr.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f := &compactext4.File{
|
||||||
|
Mode: uint16(hdr.Mode),
|
||||||
|
Atime: hdr.AccessTime,
|
||||||
|
Mtime: hdr.ModTime,
|
||||||
|
Ctime: hdr.ChangeTime,
|
||||||
|
Crtime: hdr.ModTime,
|
||||||
|
Size: hdr.Size,
|
||||||
|
Uid: uint32(hdr.Uid),
|
||||||
|
Gid: uint32(hdr.Gid),
|
||||||
|
Linkname: hdr.Linkname,
|
||||||
|
Devmajor: uint32(hdr.Devmajor),
|
||||||
|
Devminor: uint32(hdr.Devminor),
|
||||||
|
Xattrs: make(map[string][]byte),
|
||||||
|
}
|
||||||
|
for key, value := range hdr.PAXRecords {
|
||||||
|
const xattrPrefix = "SCHILY.xattr."
|
||||||
|
if strings.HasPrefix(key, xattrPrefix) {
|
||||||
|
f.Xattrs[key[len(xattrPrefix):]] = []byte(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var typ uint16
|
||||||
|
switch hdr.Typeflag {
|
||||||
|
case tar.TypeReg, tar.TypeRegA:
|
||||||
|
typ = compactext4.S_IFREG
|
||||||
|
case tar.TypeSymlink:
|
||||||
|
typ = compactext4.S_IFLNK
|
||||||
|
case tar.TypeChar:
|
||||||
|
typ = compactext4.S_IFCHR
|
||||||
|
case tar.TypeBlock:
|
||||||
|
typ = compactext4.S_IFBLK
|
||||||
|
case tar.TypeDir:
|
||||||
|
typ = compactext4.S_IFDIR
|
||||||
|
case tar.TypeFifo:
|
||||||
|
typ = compactext4.S_IFIFO
|
||||||
|
}
|
||||||
|
f.Mode &= ^compactext4.TypeMask
|
||||||
|
f.Mode |= typ
|
||||||
|
err = fs.Create(hdr.Name, f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = io.Copy(fs, t)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := fs.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if p.appendVhdFooter {
|
||||||
|
size, err := w.Seek(0, io.SeekEnd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = binary.Write(w, binary.BigEndian, makeFixedVHDFooter(size))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
76
vendor/github.com/Microsoft/hcsshim/ext4/tar2ext4/vhdfooter.go
generated
vendored
Normal file
76
vendor/github.com/Microsoft/hcsshim/ext4/tar2ext4/vhdfooter.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package tar2ext4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Constants for the VHD footer
|
||||||
|
const (
|
||||||
|
cookieMagic = "conectix"
|
||||||
|
featureMask = 0x2
|
||||||
|
fileFormatVersionMagic = 0x00010000
|
||||||
|
fixedDataOffset = -1
|
||||||
|
creatorVersionMagic = 0x000a0000
|
||||||
|
diskTypeFixed = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type vhdFooter struct {
|
||||||
|
Cookie [8]byte
|
||||||
|
Features uint32
|
||||||
|
FileFormatVersion uint32
|
||||||
|
DataOffset int64
|
||||||
|
TimeStamp uint32
|
||||||
|
CreatorApplication [4]byte
|
||||||
|
CreatorVersion uint32
|
||||||
|
CreatorHostOS [4]byte
|
||||||
|
OriginalSize int64
|
||||||
|
CurrentSize int64
|
||||||
|
DiskGeometry uint32
|
||||||
|
DiskType uint32
|
||||||
|
Checksum uint32
|
||||||
|
UniqueID [16]uint8
|
||||||
|
SavedState uint8
|
||||||
|
Reserved [427]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeFixedVHDFooter(size int64) *vhdFooter {
|
||||||
|
footer := &vhdFooter{
|
||||||
|
Features: featureMask,
|
||||||
|
FileFormatVersion: fileFormatVersionMagic,
|
||||||
|
DataOffset: fixedDataOffset,
|
||||||
|
CreatorVersion: creatorVersionMagic,
|
||||||
|
OriginalSize: size,
|
||||||
|
CurrentSize: size,
|
||||||
|
DiskType: diskTypeFixed,
|
||||||
|
UniqueID: generateUUID(),
|
||||||
|
}
|
||||||
|
copy(footer.Cookie[:], cookieMagic)
|
||||||
|
footer.Checksum = calculateCheckSum(footer)
|
||||||
|
return footer
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateCheckSum(footer *vhdFooter) uint32 {
|
||||||
|
oldchk := footer.Checksum
|
||||||
|
footer.Checksum = 0
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
binary.Write(buf, binary.BigEndian, footer)
|
||||||
|
|
||||||
|
var chk uint32
|
||||||
|
bufBytes := buf.Bytes()
|
||||||
|
for i := 0; i < len(bufBytes); i++ {
|
||||||
|
chk += uint32(bufBytes[i])
|
||||||
|
}
|
||||||
|
footer.Checksum = oldchk
|
||||||
|
return uint32(^chk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateUUID() [16]byte {
|
||||||
|
res := [16]byte{}
|
||||||
|
if _, err := rand.Read(res[:]); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
210
vendor/github.com/containerd/containerd/diff/lcow/lcow.go
generated
vendored
Normal file
210
vendor/github.com/containerd/containerd/diff/lcow/lcow.go
generated
vendored
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package lcow
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio/pkg/security"
|
||||||
|
"github.com/Microsoft/hcsshim/ext4/tar2ext4"
|
||||||
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/diff"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/containerd/containerd/metadata"
|
||||||
|
"github.com/containerd/containerd/mount"
|
||||||
|
"github.com/containerd/containerd/plugin"
|
||||||
|
digest "github.com/opencontainers/go-digest"
|
||||||
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// maxLcowVhdSizeGB is the max size in GB of any layer
|
||||||
|
maxLcowVhdSizeGB = 128 * 1024 * 1024 * 1024
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
plugin.Register(&plugin.Registration{
|
||||||
|
Type: plugin.DiffPlugin,
|
||||||
|
ID: "windows-lcow",
|
||||||
|
Requires: []plugin.Type{
|
||||||
|
plugin.MetadataPlugin,
|
||||||
|
},
|
||||||
|
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
|
||||||
|
md, err := ic.Get(plugin.MetadataPlugin)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ic.Meta.Platforms = append(ic.Meta.Platforms, ocispec.Platform{
|
||||||
|
OS: "linux",
|
||||||
|
Architecture: "amd64",
|
||||||
|
})
|
||||||
|
return NewWindowsLcowDiff(md.(*metadata.DB).ContentStore())
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareApplier handles both comparison and
|
||||||
|
// application of layer diffs.
|
||||||
|
type CompareApplier interface {
|
||||||
|
diff.Applier
|
||||||
|
diff.Comparer
|
||||||
|
}
|
||||||
|
|
||||||
|
// windowsLcowDiff does filesystem comparison and application
|
||||||
|
// for Windows specific Linux layer diffs.
|
||||||
|
type windowsLcowDiff struct {
|
||||||
|
store content.Store
|
||||||
|
}
|
||||||
|
|
||||||
|
var emptyDesc = ocispec.Descriptor{}
|
||||||
|
|
||||||
|
// NewWindowsLcowDiff is the Windows LCOW container layer implementation
|
||||||
|
// for comparing and applying Linux filesystem layers on Windows
|
||||||
|
func NewWindowsLcowDiff(store content.Store) (CompareApplier, error) {
|
||||||
|
return windowsLcowDiff{
|
||||||
|
store: store,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply applies the content associated with the provided digests onto the
|
||||||
|
// provided mounts. Archive content will be extracted and decompressed if
|
||||||
|
// necessary.
|
||||||
|
func (s windowsLcowDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount, opts ...diff.ApplyOpt) (d ocispec.Descriptor, err error) {
|
||||||
|
t1 := time.Now()
|
||||||
|
defer func() {
|
||||||
|
if err == nil {
|
||||||
|
log.G(ctx).WithFields(logrus.Fields{
|
||||||
|
"d": time.Since(t1),
|
||||||
|
"dgst": desc.Digest,
|
||||||
|
"size": desc.Size,
|
||||||
|
"media": desc.MediaType,
|
||||||
|
}).Debugf("diff applied")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var config diff.ApplyConfig
|
||||||
|
for _, o := range opts {
|
||||||
|
if err := o(ctx, desc, &config); err != nil {
|
||||||
|
return emptyDesc, errors.Wrap(err, "failed to apply config opt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layer, _, err := mountsToLayerAndParents(mounts)
|
||||||
|
if err != nil {
|
||||||
|
return emptyDesc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ra, err := s.store.ReaderAt(ctx, desc)
|
||||||
|
if err != nil {
|
||||||
|
return emptyDesc, errors.Wrap(err, "failed to get reader from content store")
|
||||||
|
}
|
||||||
|
defer ra.Close()
|
||||||
|
|
||||||
|
processor := diff.NewProcessorChain(desc.MediaType, content.NewReader(ra))
|
||||||
|
for {
|
||||||
|
if processor, err = diff.GetProcessor(ctx, processor, config.ProcessorPayloads); err != nil {
|
||||||
|
return emptyDesc, errors.Wrapf(err, "failed to get stream processor for %s", desc.MediaType)
|
||||||
|
}
|
||||||
|
if processor.MediaType() == ocispec.MediaTypeImageLayer {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer processor.Close()
|
||||||
|
|
||||||
|
// Calculate the Digest as we go
|
||||||
|
digester := digest.Canonical.Digester()
|
||||||
|
rc := &readCounter{
|
||||||
|
r: io.TeeReader(processor, digester.Hash()),
|
||||||
|
}
|
||||||
|
|
||||||
|
layerPath := path.Join(layer, "layer.vhd")
|
||||||
|
outFile, err := os.Create(layerPath)
|
||||||
|
if err != nil {
|
||||||
|
return emptyDesc, err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
outFile.Close()
|
||||||
|
os.Remove(layerPath)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = tar2ext4.Convert(rc, outFile, tar2ext4.ConvertWhiteout, tar2ext4.AppendVhdFooter, tar2ext4.MaximumDiskSize(maxLcowVhdSizeGB))
|
||||||
|
if err != nil {
|
||||||
|
return emptyDesc, errors.Wrapf(err, "failed to convert tar2ext4 vhd")
|
||||||
|
}
|
||||||
|
err = outFile.Sync()
|
||||||
|
if err != nil {
|
||||||
|
return emptyDesc, errors.Wrapf(err, "failed to sync tar2ext4 vhd to disk")
|
||||||
|
}
|
||||||
|
outFile.Close()
|
||||||
|
|
||||||
|
err = security.GrantVmGroupAccess(layerPath)
|
||||||
|
if err != nil {
|
||||||
|
return emptyDesc, errors.Wrapf(err, "failed GrantVmGroupAccess on layer vhd: %v", layerPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ocispec.Descriptor{
|
||||||
|
MediaType: ocispec.MediaTypeImageLayer,
|
||||||
|
Size: rc.c,
|
||||||
|
Digest: digester.Digest(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare creates a diff between the given mounts and uploads the result
|
||||||
|
// to the content store.
|
||||||
|
func (s windowsLcowDiff) Compare(ctx context.Context, lower, upper []mount.Mount, opts ...diff.Opt) (d ocispec.Descriptor, err error) {
|
||||||
|
return emptyDesc, errdefs.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
type readCounter struct {
|
||||||
|
r io.Reader
|
||||||
|
c int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *readCounter) Read(p []byte) (n int, err error) {
|
||||||
|
n, err = rc.r.Read(p)
|
||||||
|
rc.c += int64(n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func mountsToLayerAndParents(mounts []mount.Mount) (string, []string, error) {
|
||||||
|
if len(mounts) != 1 {
|
||||||
|
return "", nil, errors.Wrap(errdefs.ErrInvalidArgument, "number of mounts should always be 1 for Windows lcow-layers")
|
||||||
|
}
|
||||||
|
mnt := mounts[0]
|
||||||
|
if mnt.Type != "lcow-layer" {
|
||||||
|
return "", nil, errors.Wrap(errdefs.ErrInvalidArgument, "mount layer type must be lcow-layer")
|
||||||
|
}
|
||||||
|
|
||||||
|
parentLayerPaths, err := mnt.GetParentPaths()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return mnt.Source, parentLayerPaths, nil
|
||||||
|
}
|
193
vendor/github.com/containerd/containerd/diff/windows/windows.go
generated
vendored
Normal file
193
vendor/github.com/containerd/containerd/diff/windows/windows.go
generated
vendored
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
winio "github.com/Microsoft/go-winio"
|
||||||
|
"github.com/containerd/containerd/archive"
|
||||||
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/diff"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/containerd/containerd/metadata"
|
||||||
|
"github.com/containerd/containerd/mount"
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
|
"github.com/containerd/containerd/plugin"
|
||||||
|
digest "github.com/opencontainers/go-digest"
|
||||||
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
plugin.Register(&plugin.Registration{
|
||||||
|
Type: plugin.DiffPlugin,
|
||||||
|
ID: "windows",
|
||||||
|
Requires: []plugin.Type{
|
||||||
|
plugin.MetadataPlugin,
|
||||||
|
},
|
||||||
|
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
|
||||||
|
md, err := ic.Get(plugin.MetadataPlugin)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ic.Meta.Platforms = append(ic.Meta.Platforms, platforms.DefaultSpec())
|
||||||
|
return NewWindowsDiff(md.(*metadata.DB).ContentStore())
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareApplier handles both comparison and
|
||||||
|
// application of layer diffs.
|
||||||
|
type CompareApplier interface {
|
||||||
|
diff.Applier
|
||||||
|
diff.Comparer
|
||||||
|
}
|
||||||
|
|
||||||
|
// windowsDiff does filesystem comparison and application
|
||||||
|
// for Windows specific layer diffs.
|
||||||
|
type windowsDiff struct {
|
||||||
|
store content.Store
|
||||||
|
}
|
||||||
|
|
||||||
|
var emptyDesc = ocispec.Descriptor{}
|
||||||
|
|
||||||
|
// NewWindowsDiff is the Windows container layer implementation
|
||||||
|
// for comparing and applying filesystem layers
|
||||||
|
func NewWindowsDiff(store content.Store) (CompareApplier, error) {
|
||||||
|
return windowsDiff{
|
||||||
|
store: store,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply applies the content associated with the provided digests onto the
|
||||||
|
// provided mounts. Archive content will be extracted and decompressed if
|
||||||
|
// necessary.
|
||||||
|
func (s windowsDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount, opts ...diff.ApplyOpt) (d ocispec.Descriptor, err error) {
|
||||||
|
t1 := time.Now()
|
||||||
|
defer func() {
|
||||||
|
if err == nil {
|
||||||
|
log.G(ctx).WithFields(logrus.Fields{
|
||||||
|
"d": time.Since(t1),
|
||||||
|
"dgst": desc.Digest,
|
||||||
|
"size": desc.Size,
|
||||||
|
"media": desc.MediaType,
|
||||||
|
}).Debugf("diff applied")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var config diff.ApplyConfig
|
||||||
|
for _, o := range opts {
|
||||||
|
if err := o(ctx, desc, &config); err != nil {
|
||||||
|
return emptyDesc, errors.Wrap(err, "failed to apply config opt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ra, err := s.store.ReaderAt(ctx, desc)
|
||||||
|
if err != nil {
|
||||||
|
return emptyDesc, errors.Wrap(err, "failed to get reader from content store")
|
||||||
|
}
|
||||||
|
defer ra.Close()
|
||||||
|
|
||||||
|
processor := diff.NewProcessorChain(desc.MediaType, content.NewReader(ra))
|
||||||
|
for {
|
||||||
|
if processor, err = diff.GetProcessor(ctx, processor, config.ProcessorPayloads); err != nil {
|
||||||
|
return emptyDesc, errors.Wrapf(err, "failed to get stream processor for %s", desc.MediaType)
|
||||||
|
}
|
||||||
|
if processor.MediaType() == ocispec.MediaTypeImageLayer {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer processor.Close()
|
||||||
|
|
||||||
|
digester := digest.Canonical.Digester()
|
||||||
|
rc := &readCounter{
|
||||||
|
r: io.TeeReader(processor, digester.Hash()),
|
||||||
|
}
|
||||||
|
|
||||||
|
layer, parentLayerPaths, err := mountsToLayerAndParents(mounts)
|
||||||
|
if err != nil {
|
||||||
|
return emptyDesc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO darrenstahlmsft: When this is done isolated, we should disable these.
|
||||||
|
// it currently cannot be disabled, unless we add ref counting. Since this is
|
||||||
|
// temporary, leaving it enabled is OK for now.
|
||||||
|
if err := winio.EnableProcessPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege}); err != nil {
|
||||||
|
return emptyDesc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := archive.Apply(ctx, layer, rc, archive.WithParentLayers(parentLayerPaths), archive.AsWindowsContainerLayer()); err != nil {
|
||||||
|
return emptyDesc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read any trailing data
|
||||||
|
if _, err := io.Copy(ioutil.Discard, rc); err != nil {
|
||||||
|
return emptyDesc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ocispec.Descriptor{
|
||||||
|
MediaType: ocispec.MediaTypeImageLayer,
|
||||||
|
Size: rc.c,
|
||||||
|
Digest: digester.Digest(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare creates a diff between the given mounts and uploads the result
|
||||||
|
// to the content store.
|
||||||
|
func (s windowsDiff) Compare(ctx context.Context, lower, upper []mount.Mount, opts ...diff.Opt) (d ocispec.Descriptor, err error) {
|
||||||
|
return emptyDesc, errdefs.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
type readCounter struct {
|
||||||
|
r io.Reader
|
||||||
|
c int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *readCounter) Read(p []byte) (n int, err error) {
|
||||||
|
n, err = rc.r.Read(p)
|
||||||
|
rc.c += int64(n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func mountsToLayerAndParents(mounts []mount.Mount) (string, []string, error) {
|
||||||
|
if len(mounts) != 1 {
|
||||||
|
return "", nil, errors.Wrap(errdefs.ErrInvalidArgument, "number of mounts should always be 1 for Windows layers")
|
||||||
|
}
|
||||||
|
mnt := mounts[0]
|
||||||
|
if mnt.Type != "windows-layer" {
|
||||||
|
// This is a special case error. When this is received the diff service
|
||||||
|
// will attempt the next differ in the chain which for Windows is the
|
||||||
|
// lcow differ that we want.
|
||||||
|
return "", nil, errdefs.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
parentLayerPaths, err := mnt.GetParentPaths()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return mnt.Source, parentLayerPaths, nil
|
||||||
|
}
|
338
vendor/github.com/containerd/containerd/snapshots/windows/windows.go
generated
vendored
Normal file
338
vendor/github.com/containerd/containerd/snapshots/windows/windows.go
generated
vendored
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
winfs "github.com/Microsoft/go-winio/pkg/fs"
|
||||||
|
"github.com/Microsoft/go-winio/vhd"
|
||||||
|
"github.com/Microsoft/hcsshim"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/containerd/containerd/mount"
|
||||||
|
"github.com/containerd/containerd/plugin"
|
||||||
|
"github.com/containerd/containerd/snapshots"
|
||||||
|
"github.com/containerd/containerd/snapshots/storage"
|
||||||
|
"github.com/containerd/continuity/fs"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
plugin.Register(&plugin.Registration{
|
||||||
|
Type: plugin.SnapshotPlugin,
|
||||||
|
ID: "windows",
|
||||||
|
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
|
||||||
|
return NewSnapshotter(ic.Root)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type snapshotter struct {
|
||||||
|
root string
|
||||||
|
info hcsshim.DriverInfo
|
||||||
|
ms *storage.MetaStore
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSnapshotter returns a new windows snapshotter
|
||||||
|
func NewSnapshotter(root string) (snapshots.Snapshotter, error) {
|
||||||
|
fsType, err := winfs.GetFileSystemType(root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if strings.ToLower(fsType) != "ntfs" {
|
||||||
|
return nil, errors.Wrapf(errdefs.ErrInvalidArgument, "%s is not on an NTFS volume - only NTFS volumes are supported", root)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(root, 0700); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ms, err := storage.NewMetaStore(filepath.Join(root, "metadata.db"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Mkdir(filepath.Join(root, "snapshots"), 0700); err != nil && !os.IsExist(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &snapshotter{
|
||||||
|
info: hcsshim.DriverInfo{
|
||||||
|
HomeDir: filepath.Join(root, "snapshots"),
|
||||||
|
},
|
||||||
|
root: root,
|
||||||
|
ms: ms,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat returns the info for an active or committed snapshot by name or
|
||||||
|
// key.
|
||||||
|
//
|
||||||
|
// Should be used for parent resolution, existence checks and to discern
|
||||||
|
// the kind of snapshot.
|
||||||
|
func (s *snapshotter) Stat(ctx context.Context, key string) (snapshots.Info, error) {
|
||||||
|
ctx, t, err := s.ms.TransactionContext(ctx, false)
|
||||||
|
if err != nil {
|
||||||
|
return snapshots.Info{}, err
|
||||||
|
}
|
||||||
|
defer t.Rollback()
|
||||||
|
|
||||||
|
_, info, _, err := storage.GetInfo(ctx, key)
|
||||||
|
return info, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snapshotter) Update(ctx context.Context, info snapshots.Info, fieldpaths ...string) (snapshots.Info, error) {
|
||||||
|
ctx, t, err := s.ms.TransactionContext(ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
return snapshots.Info{}, err
|
||||||
|
}
|
||||||
|
defer t.Rollback()
|
||||||
|
|
||||||
|
info, err = storage.UpdateInfo(ctx, info, fieldpaths...)
|
||||||
|
if err != nil {
|
||||||
|
return snapshots.Info{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.Commit(); err != nil {
|
||||||
|
return snapshots.Info{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snapshotter) Usage(ctx context.Context, key string) (snapshots.Usage, error) {
|
||||||
|
ctx, t, err := s.ms.TransactionContext(ctx, false)
|
||||||
|
if err != nil {
|
||||||
|
return snapshots.Usage{}, err
|
||||||
|
}
|
||||||
|
defer t.Rollback()
|
||||||
|
|
||||||
|
_, info, usage, err := storage.GetInfo(ctx, key)
|
||||||
|
if err != nil {
|
||||||
|
return snapshots.Usage{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.Kind == snapshots.KindActive {
|
||||||
|
du := fs.Usage{
|
||||||
|
Size: 0,
|
||||||
|
}
|
||||||
|
usage = snapshots.Usage(du)
|
||||||
|
}
|
||||||
|
|
||||||
|
return usage, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {
|
||||||
|
return s.createSnapshot(ctx, snapshots.KindActive, key, parent, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snapshotter) View(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {
|
||||||
|
return s.createSnapshot(ctx, snapshots.KindView, key, parent, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mounts returns the mounts for the transaction identified by key. Can be
|
||||||
|
// called on an read-write or readonly transaction.
|
||||||
|
//
|
||||||
|
// This can be used to recover mounts after calling View or Prepare.
|
||||||
|
func (s *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) {
|
||||||
|
ctx, t, err := s.ms.TransactionContext(ctx, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer t.Rollback()
|
||||||
|
|
||||||
|
snapshot, err := storage.GetSnapshot(ctx, key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to get snapshot mount")
|
||||||
|
}
|
||||||
|
return s.mounts(snapshot), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) error {
|
||||||
|
ctx, t, err := s.ms.TransactionContext(ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer t.Rollback()
|
||||||
|
|
||||||
|
usage := fs.Usage{
|
||||||
|
Size: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = storage.CommitActive(ctx, key, name, snapshots.Usage(usage), opts...); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to commit snapshot")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.Commit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove abandons the transaction identified by key. All resources
|
||||||
|
// associated with the key will be removed.
|
||||||
|
func (s *snapshotter) Remove(ctx context.Context, key string) error {
|
||||||
|
ctx, t, err := s.ms.TransactionContext(ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer t.Rollback()
|
||||||
|
|
||||||
|
id, _, err := storage.Remove(ctx, key)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to remove")
|
||||||
|
}
|
||||||
|
|
||||||
|
path := s.getSnapshotDir(id)
|
||||||
|
renamedID := "rm-" + id
|
||||||
|
renamed := s.getSnapshotDir(renamedID)
|
||||||
|
if err := os.Rename(path, renamed); err != nil && !os.IsNotExist(err) {
|
||||||
|
if !os.IsPermission(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// If permission denied, it's possible that the scratch is still mounted, an
|
||||||
|
// artifact after a hard daemon crash for example. Worth a shot to try detaching it
|
||||||
|
// before retrying the rename.
|
||||||
|
if detachErr := vhd.DetachVhd(filepath.Join(path, "sandbox.vhdx")); detachErr != nil {
|
||||||
|
return errors.Wrapf(err, "failed to detach VHD: %s", detachErr)
|
||||||
|
}
|
||||||
|
if renameErr := os.Rename(path, renamed); renameErr != nil && !os.IsNotExist(renameErr) {
|
||||||
|
return errors.Wrapf(err, "second rename attempt following detach failed: %s", renameErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.Commit(); err != nil {
|
||||||
|
if err1 := os.Rename(renamed, path); err1 != nil {
|
||||||
|
// May cause inconsistent data on disk
|
||||||
|
log.G(ctx).WithError(err1).WithField("path", renamed).Errorf("Failed to rename after failed commit")
|
||||||
|
}
|
||||||
|
return errors.Wrap(err, "failed to commit")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := hcsshim.DestroyLayer(s.info, renamedID); err != nil {
|
||||||
|
// Must be cleaned up, any "rm-*" could be removed if no active transactions
|
||||||
|
log.G(ctx).WithError(err).WithField("path", renamed).Warnf("Failed to remove root filesystem")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk the committed snapshots.
|
||||||
|
func (s *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error) error {
|
||||||
|
ctx, t, err := s.ms.TransactionContext(ctx, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer t.Rollback()
|
||||||
|
|
||||||
|
return storage.WalkInfo(ctx, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the snapshotter
|
||||||
|
func (s *snapshotter) Close() error {
|
||||||
|
return s.ms.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snapshotter) mounts(sn storage.Snapshot) []mount.Mount {
|
||||||
|
var (
|
||||||
|
roFlag string
|
||||||
|
source string
|
||||||
|
parentLayerPaths []string
|
||||||
|
)
|
||||||
|
|
||||||
|
if sn.Kind == snapshots.KindView {
|
||||||
|
roFlag = "ro"
|
||||||
|
} else {
|
||||||
|
roFlag = "rw"
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sn.ParentIDs) == 0 || sn.Kind == snapshots.KindActive {
|
||||||
|
source = s.getSnapshotDir(sn.ID)
|
||||||
|
parentLayerPaths = s.parentIDsToParentPaths(sn.ParentIDs)
|
||||||
|
} else {
|
||||||
|
source = s.getSnapshotDir(sn.ParentIDs[0])
|
||||||
|
parentLayerPaths = s.parentIDsToParentPaths(sn.ParentIDs[1:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// error is not checked here, as a string array will never fail to Marshal
|
||||||
|
parentLayersJSON, _ := json.Marshal(parentLayerPaths)
|
||||||
|
parentLayersOption := mount.ParentLayerPathsFlag + string(parentLayersJSON)
|
||||||
|
|
||||||
|
var mounts []mount.Mount
|
||||||
|
mounts = append(mounts, mount.Mount{
|
||||||
|
Source: source,
|
||||||
|
Type: "windows-layer",
|
||||||
|
Options: []string{
|
||||||
|
roFlag,
|
||||||
|
parentLayersOption,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return mounts
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snapshotter) getSnapshotDir(id string) string {
|
||||||
|
return filepath.Join(s.root, "snapshots", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, key, parent string, opts []snapshots.Opt) ([]mount.Mount, error) {
|
||||||
|
ctx, t, err := s.ms.TransactionContext(ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer t.Rollback()
|
||||||
|
|
||||||
|
newSnapshot, err := storage.CreateSnapshot(ctx, kind, key, parent, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to create snapshot")
|
||||||
|
}
|
||||||
|
|
||||||
|
if kind == snapshots.KindActive {
|
||||||
|
parentLayerPaths := s.parentIDsToParentPaths(newSnapshot.ParentIDs)
|
||||||
|
|
||||||
|
var parentPath string
|
||||||
|
if len(parentLayerPaths) != 0 {
|
||||||
|
parentPath = parentLayerPaths[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := hcsshim.CreateSandboxLayer(s.info, newSnapshot.ID, parentPath, parentLayerPaths); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to create sandbox layer")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(darrenstahlmsft): Allow changing sandbox size
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.Commit(); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "commit failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mounts(newSnapshot), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snapshotter) parentIDsToParentPaths(parentIDs []string) []string {
|
||||||
|
var parentLayerPaths []string
|
||||||
|
for _, ID := range parentIDs {
|
||||||
|
parentLayerPaths = append(parentLayerPaths, s.getSnapshotDir(ID))
|
||||||
|
}
|
||||||
|
return parentLayerPaths
|
||||||
|
}
|
9
vendor/github.com/konsorten/go-windows-terminal-sequences/LICENSE
generated
vendored
Normal file
9
vendor/github.com/konsorten/go-windows-terminal-sequences/LICENSE
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2017 marvin + konsorten GmbH (open-source@konsorten.de)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
40
vendor/github.com/konsorten/go-windows-terminal-sequences/README.md
generated
vendored
Normal file
40
vendor/github.com/konsorten/go-windows-terminal-sequences/README.md
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Windows Terminal Sequences
|
||||||
|
|
||||||
|
This library allow for enabling Windows terminal color support for Go.
|
||||||
|
|
||||||
|
See [Console Virtual Terminal Sequences](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences) for details.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
sequences "github.com/konsorten/go-windows-terminal-sequences"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sequences.EnableVirtualTerminalProcessing(syscall.Stdout, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
The tool is sponsored by the [marvin + konsorten GmbH](http://www.konsorten.de).
|
||||||
|
|
||||||
|
We thank all the authors who provided code to this library:
|
||||||
|
|
||||||
|
* Felix Kollmann
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2018 marvin + konsorten GmbH (open-source@konsorten.de)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
vendor/github.com/konsorten/go-windows-terminal-sequences/go.mod
generated
vendored
Normal file
1
vendor/github.com/konsorten/go-windows-terminal-sequences/go.mod
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
module github.com/konsorten/go-windows-terminal-sequences
|
36
vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go
generated
vendored
Normal file
36
vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package sequences
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
kernel32Dll *syscall.LazyDLL = syscall.NewLazyDLL("Kernel32.dll")
|
||||||
|
setConsoleMode *syscall.LazyProc = kernel32Dll.NewProc("SetConsoleMode")
|
||||||
|
)
|
||||||
|
|
||||||
|
func EnableVirtualTerminalProcessing(stream syscall.Handle, enable bool) error {
|
||||||
|
const ENABLE_VIRTUAL_TERMINAL_PROCESSING uint32 = 0x4
|
||||||
|
|
||||||
|
var mode uint32
|
||||||
|
err := syscall.GetConsoleMode(syscall.Stdout, &mode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if enable {
|
||||||
|
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||||
|
} else {
|
||||||
|
mode &^= ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _, err := setConsoleMode.Call(uintptr(unsafe.Pointer(stream)), uintptr(mode))
|
||||||
|
if ret == 0 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user