|
@@ -6,6 +6,7 @@ import (
|
|
|
"bufio"
|
|
|
"bytes"
|
|
|
"encoding/json"
|
|
|
+ "errors"
|
|
|
"fmt"
|
|
|
"io"
|
|
|
"io/ioutil"
|
|
@@ -74,6 +75,15 @@ func isTP5OrOlder() bool {
|
|
|
// InitFilter returns a new Windows storage filter driver.
|
|
|
func InitFilter(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
|
|
|
logrus.Debugf("WindowsGraphDriver InitFilter at %s", home)
|
|
|
+
|
|
|
+ fsType, err := getFileSystemType(string(home[0]))
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ if strings.ToLower(fsType) == "refs" {
|
|
|
+ return nil, fmt.Errorf("%s is on an ReFS volume - ReFS volumes are not supported", home)
|
|
|
+ }
|
|
|
+
|
|
|
d := &Driver{
|
|
|
info: hcsshim.DriverInfo{
|
|
|
HomeDir: home,
|
|
@@ -85,6 +95,37 @@ func InitFilter(home string, options []string, uidMaps, gidMaps []idtools.IDMap)
|
|
|
return d, nil
|
|
|
}
|
|
|
|
|
|
+// 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
|
|
|
+}
|
|
|
+
|
|
|
+// 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(drive string) (fsType string, hr error) {
|
|
|
+ var (
|
|
|
+ modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
|
+ procGetVolumeInformation = modkernel32.NewProc("GetVolumeInformationW")
|
|
|
+ buf = make([]uint16, 255)
|
|
|
+ size = syscall.MAX_PATH + 1
|
|
|
+ )
|
|
|
+ if len(drive) != 1 {
|
|
|
+ hr = errors.New("getFileSystemType must be called with a drive letter")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ drive += `:\`
|
|
|
+ n := uintptr(unsafe.Pointer(nil))
|
|
|
+ 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)
|
|
|
+ if int32(r0) < 0 {
|
|
|
+ hr = syscall.Errno(win32FromHresult(r0))
|
|
|
+ }
|
|
|
+ fsType = syscall.UTF16ToString(buf)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
// String returns the string representation of a driver. This should match
|
|
|
// the name the graph driver has been registered with.
|
|
|
func (d *Driver) String() string {
|