summaryrefslogtreecommitdiff
path: root/vendor/github.com/Microsoft/go-winio/vhd/vhd.go
blob: 229ac25565a54c42e59fe96e71fafac09c3c0f5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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,
		&parameters,
		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),
		&parameters,
		&handle); err != nil {
		return 0, err
	}
	return handle, nil
}