Skip EA processing for volumes that do not support EA

This commit is contained in:
aneesh-n 2024-08-03 16:03:30 -06:00
parent a48baf6f3a
commit 56113a8da7
No known key found for this signature in database
GPG key ID: 6F5A52831C046F44
2 changed files with 58 additions and 2 deletions

View file

@ -53,6 +53,15 @@ var (
errInvalidEaBuffer = errors.New("invalid extended attribute buffer") errInvalidEaBuffer = errors.New("invalid extended attribute buffer")
errEaNameTooLarge = errors.New("extended attribute name too large") errEaNameTooLarge = errors.New("extended attribute name too large")
errEaValueTooLarge = errors.New("extended attribute value too large") errEaValueTooLarge = errors.New("extended attribute value too large")
kernel32dll = syscall.NewLazyDLL("kernel32.dll")
procGetVolumeInformationW = kernel32dll.NewProc("GetVolumeInformationW")
)
const (
// fileSupportsExtendedAttributes is a bitmask that indicates whether the file system supports extended attributes.
fileSupportsExtendedAttributes = 0x00000004
) )
// ExtendedAttribute represents a single Windows EA. // ExtendedAttribute represents a single Windows EA.
@ -283,3 +292,34 @@ func setFileEA(handle windows.Handle, iosb *ioStatusBlock, buf *uint8, bufLen ui
status = ntStatus(r0) status = ntStatus(r0)
return return
} }
// PathSupportsExtendedAttributes returns true if the path supports extended attributes.
func PathSupportsExtendedAttributes(path string) (bool, error) {
var (
volumeName [syscall.MAX_PATH + 1]uint16
fsName [syscall.MAX_PATH + 1]uint16
volumeSerial uint32
maxComponentLen uint32
fileSystemFlags uint32
)
utf16Path, err := windows.UTF16PtrFromString(path)
if err != nil {
return false, err
}
ret, _, err := procGetVolumeInformationW.Call(
uintptr(unsafe.Pointer(utf16Path)),
uintptr(unsafe.Pointer(&volumeName[0])),
uintptr(len(volumeName)),
uintptr(unsafe.Pointer(&volumeSerial)),
uintptr(unsafe.Pointer(&maxComponentLen)),
uintptr(unsafe.Pointer(&fileSystemFlags)),
uintptr(unsafe.Pointer(&fsName[0])),
uintptr(len(fsName)),
)
if ret == 0 {
return false, err
}
supportsEAs := (fileSystemFlags & fileSupportsExtendedAttributes) != 0
return supportsEAs, nil
}

View file

@ -32,6 +32,9 @@ var (
modAdvapi32 = syscall.NewLazyDLL("advapi32.dll") modAdvapi32 = syscall.NewLazyDLL("advapi32.dll")
procEncryptFile = modAdvapi32.NewProc("EncryptFileW") procEncryptFile = modAdvapi32.NewProc("EncryptFileW")
procDecryptFile = modAdvapi32.NewProc("DecryptFileW") procDecryptFile = modAdvapi32.NewProc("DecryptFileW")
// eaUnsupportedVolumesMap is a map of volumes that do not support extended attributes.
eaUnsupportedVolumesMap = map[string]bool{}
) )
// mknod is not supported on Windows. // mknod is not supported on Windows.
@ -358,7 +361,20 @@ func (node *Node) fillGenericAttributes(path string, fi os.FileInfo, stat *statT
// Also do not allow processing of extended attributes for ADS. // Also do not allow processing of extended attributes for ADS.
return false, nil return false, nil
} }
if !strings.HasSuffix(filepath.Clean(path), `\`) { if strings.HasSuffix(filepath.Clean(path), `\`) {
// This path is a volume
supportsEAs, err := fs.PathSupportsExtendedAttributes(path)
if err != nil {
return false, err
}
if supportsEAs {
delete(eaUnsupportedVolumesMap, filepath.VolumeName(path))
} else {
// Add the volume to the map of volumes that do not support extended attributes.
eaUnsupportedVolumesMap[filepath.VolumeName(path)] = true
}
return supportsEAs, nil
} else {
// Do not process file attributes and created time for windows directories like // Do not process file attributes and created time for windows directories like
// C:, D: // C:, D:
// Filepath.Clean(path) ends with '\' for Windows root drives only. // Filepath.Clean(path) ends with '\' for Windows root drives only.
@ -375,8 +391,8 @@ func (node *Node) fillGenericAttributes(path string, fi os.FileInfo, stat *statT
FileAttributes: &stat.FileAttributes, FileAttributes: &stat.FileAttributes,
SecurityDescriptor: sd, SecurityDescriptor: sd,
}) })
return !eaUnsupportedVolumesMap[filepath.VolumeName(path)], err
} }
return true, err
} }
// windowsAttrsToGenericAttributes converts the WindowsAttributes to a generic attributes map using reflection // windowsAttrsToGenericAttributes converts the WindowsAttributes to a generic attributes map using reflection