Browse code

Merge pull request #25509 from Microsoft/jjh/23079

Windows: Block ReFS file systems

Michael Crosby authored on 2016/08/13 01:32:22
Showing 1 changed files
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"bufio"
7 7
 	"bytes"
8 8
 	"encoding/json"
9
+	"errors"
9 10
 	"fmt"
10 11
 	"io"
11 12
 	"io/ioutil"
... ...
@@ -74,6 +75,15 @@ func isTP5OrOlder() bool {
74 74
 // InitFilter returns a new Windows storage filter driver.
75 75
 func InitFilter(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
76 76
 	logrus.Debugf("WindowsGraphDriver InitFilter at %s", home)
77
+
78
+	fsType, err := getFileSystemType(string(home[0]))
79
+	if err != nil {
80
+		return nil, err
81
+	}
82
+	if strings.ToLower(fsType) == "refs" {
83
+		return nil, fmt.Errorf("%s is on an ReFS volume - ReFS volumes are not supported", home)
84
+	}
85
+
77 86
 	d := &Driver{
78 87
 		info: hcsshim.DriverInfo{
79 88
 			HomeDir: home,
... ...
@@ -85,6 +95,37 @@ func InitFilter(home string, options []string, uidMaps, gidMaps []idtools.IDMap)
85 85
 	return d, nil
86 86
 }
87 87
 
88
+// win32FromHresult is a helper function to get the win32 error code from an HRESULT
89
+func win32FromHresult(hr uintptr) uintptr {
90
+	if hr&0x1fff0000 == 0x00070000 {
91
+		return hr & 0xffff
92
+	}
93
+	return hr
94
+}
95
+
96
+// getFileSystemType obtains the type of a file system through GetVolumeInformation
97
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx
98
+func getFileSystemType(drive string) (fsType string, hr error) {
99
+	var (
100
+		modkernel32              = syscall.NewLazyDLL("kernel32.dll")
101
+		procGetVolumeInformation = modkernel32.NewProc("GetVolumeInformationW")
102
+		buf                      = make([]uint16, 255)
103
+		size                     = syscall.MAX_PATH + 1
104
+	)
105
+	if len(drive) != 1 {
106
+		hr = errors.New("getFileSystemType must be called with a drive letter")
107
+		return
108
+	}
109
+	drive += `:\`
110
+	n := uintptr(unsafe.Pointer(nil))
111
+	r0, _, _ := syscall.Syscall9(procGetVolumeInformation.Addr(), 8, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(drive))), n, n, n, n, n, uintptr(unsafe.Pointer(&buf[0])), uintptr(size), 0)
112
+	if int32(r0) < 0 {
113
+		hr = syscall.Errno(win32FromHresult(r0))
114
+	}
115
+	fsType = syscall.UTF16ToString(buf)
116
+	return
117
+}
118
+
88 119
 // String returns the string representation of a driver. This should match
89 120
 // the name the graph driver has been registered with.
90 121
 func (d *Driver) String() string {