Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/improvements to the windows filesystem implementation #210

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 43 additions & 39 deletions pkg/filesystem/local_directory_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func (d *localDirectory) openNt(name path.Component, access, disposition uint32,
var options uint32 = windows.FILE_NON_DIRECTORY_FILE | windows.FILE_SYNCHRONOUS_IO_NONALERT
if openReparsePoint {
options |= windows.FILE_OPEN_REPARSE_POINT
// Do not overwrite file attributes. Use dispostion FILE_OPEN.
// Do not overwrite file attributes. Use disposition FILE_OPEN.
err := ntCreateFile(&handle, access, d.handle, name.String(), windows.FILE_OPEN, options)
if err != nil {
// The file does not exist, so it cannot be a reparse point.
Expand Down Expand Up @@ -395,6 +395,7 @@ func (d *localDirectory) lstat(name path.Component) (FileType, error) {
if err != nil {
return FileTypeOther, err
}
defer windows.CloseHandle(handle)
var fileInfo windows.ByHandleFileInformation
err = windows.GetFileInformationByHandle(handle, &fileInfo)
if err != nil {
Expand Down Expand Up @@ -440,49 +441,51 @@ func (d *localDirectory) Mknod(name path.Component, perm os.FileMode, deviceNumb
}

func readdirnames(handle windows.Handle) ([]string, error) {
outBufferSize := uint32(512)
outBuffer := make([]byte, outBufferSize)
firstIteration := true
filledSize := uint32(256)
names := make([]string, 0)

for {
err := windows.GetFileInformationByHandleEx(handle, windows.FileFullDirectoryInfo,
&outBuffer[0], outBufferSize)
if err == nil {
break
}
if err.(syscall.Errno) == windows.ERROR_NO_MORE_FILES {
if firstIteration {
return []string{}, nil
outBufferSize := uint32(filledSize * 2)
outBuffer := make([]byte, outBufferSize)
err := windows.GetFileInformationByHandleEx(handle, windows.FileFullDirectoryInfo, &outBuffer[0], outBufferSize)
if err != nil {
// Require a bigger buffer.
if err.(syscall.Errno) == windows.ERROR_MORE_DATA {
filledSize *= 2
continue
}
break
}
if err.(syscall.Errno) == windows.ERROR_MORE_DATA {
outBufferSize *= 2
outBuffer = make([]byte, outBufferSize)
} else {
return nil, err
}
firstIteration = false
}
names := make([]string, 0)
offset := ^(uint32(0))
dirInfoPtr := (*windowsext.FILE_FULL_DIR_INFO)(unsafe.Pointer(&outBuffer[0]))
for offset != 0 {
offset = dirInfoPtr.NextEntryOffset
fileNameLen := int(dirInfoPtr.FileNameLength) / 2
fileNameUTF16 := make([]uint16, fileNameLen)
targetPtr := unsafe.Pointer(&dirInfoPtr.FileName[0])
for i := 0; i < fileNameLen; i++ {
fileNameUTF16[i] = *(*uint16)(targetPtr)
targetPtr = unsafe.Pointer(uintptr(targetPtr) + uintptr(2))
// Done.
if err.(syscall.Errno) == windows.ERROR_NO_MORE_FILES {
break
}

return []string{}, err
}
dirInfoPtr = (*windowsext.FILE_FULL_DIR_INFO)(unsafe.Pointer(uintptr(unsafe.Pointer(dirInfoPtr)) + uintptr(offset)))

fileName := windows.UTF16ToString(fileNameUTF16)
if fileName == "." || fileName == ".." {
continue
offset := ^(uint32(0))
filledSize = 0
dirInfoPtr := (*windowsext.FILE_FULL_DIR_INFO)(unsafe.Pointer(&outBuffer[0]))
for offset != 0 {
offset = dirInfoPtr.NextEntryOffset
fileNameLen := int(dirInfoPtr.FileNameLength) / 2
filledSize += uint32(unsafe.Sizeof(windowsext.FILE_FULL_DIR_INFO{})) + uint32(dirInfoPtr.FileNameLength)

fileNameUTF16 := make([]uint16, fileNameLen)
targetPtr := unsafe.Pointer(&dirInfoPtr.FileName[0])
for i := 0; i < fileNameLen; i++ {
fileNameUTF16[i] = *(*uint16)(targetPtr)
targetPtr = unsafe.Pointer(uintptr(targetPtr) + uintptr(2))
}
dirInfoPtr = (*windowsext.FILE_FULL_DIR_INFO)(unsafe.Pointer(uintptr(unsafe.Pointer(dirInfoPtr)) + uintptr(offset)))

fileName := windows.UTF16ToString(fileNameUTF16)
if fileName == "." || fileName == ".." {
continue
}
names = append(names, fileName)
}
names = append(names, fileName)
}

return names, nil
}

Expand Down Expand Up @@ -513,6 +516,7 @@ func (d *localDirectory) Readlink(name path.Component) (path.Parser, error) {
if err != nil {
return nil, err
}
defer windows.CloseHandle(handle)
outBufferSize := uint32(512)
outBuffer := make([]byte, outBufferSize)
var returned uint32
Expand Down Expand Up @@ -855,7 +859,7 @@ func buildFileLinkInfo(root windows.Handle, name []uint16) ([]byte, uint32) {

func createNTFSHardlink(oldHandle windows.Handle, oldName string, newHandle windows.Handle, newName string) error {
var handle windows.Handle
err := ntCreateFile(&handle, windows.FILE_GENERIC_READ|windows.FILE_GENERIC_WRITE, oldHandle, oldName, windows.FILE_OPEN, 0)
err := ntCreateFile(&handle, windows.FILE_GENERIC_READ, oldHandle, oldName, windows.FILE_OPEN, 0)
if err != nil {
return err
}
Expand Down