vendor tsgo
This commit is contained in:
74
tools/tsgo/internal/fswatch/walkdir_windows.go
Normal file
74
tools/tsgo/internal/fswatch/walkdir_windows.go
Normal file
@@ -0,0 +1,74 @@
|
||||
//go:build windows
|
||||
|
||||
package fswatch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// walkDir walks a directory tree on Windows using FindFirstFile/FindNextFile.
|
||||
func walkDir(dir string, recursive bool, fn func(path string, isDir bool) error) error {
|
||||
rootPtr, err := windows.UTF16PtrFromString(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var rootData windows.Win32FileAttributeData
|
||||
if err := windows.GetFileAttributesEx(rootPtr, windows.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&rootData))); err != nil {
|
||||
return fmt.Errorf("error opening directory: %w", err)
|
||||
}
|
||||
if rootData.FileAttributes&windows.FILE_ATTRIBUTE_DIRECTORY == 0 ||
|
||||
rootData.FileAttributes&windows.FILE_ATTRIBUTE_REPARSE_POINT != 0 {
|
||||
return syscall.ENOTDIR
|
||||
}
|
||||
if fn != nil {
|
||||
if err := fn(dir, true); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
stack := []string{dir}
|
||||
for len(stack) > 0 {
|
||||
path := stack[len(stack)-1]
|
||||
stack = stack[:len(stack)-1]
|
||||
|
||||
spec := path + "\\*"
|
||||
specPtr, err := windows.UTF16PtrFromString(spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var ffd windows.Win32finddata
|
||||
hFind, err := windows.FindFirstFile(specPtr, &ffd)
|
||||
if err != nil {
|
||||
if path == dir {
|
||||
return fmt.Errorf("error opening directory: %w", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
for {
|
||||
name := windows.UTF16ToString(ffd.FileName[:])
|
||||
if name != "." && name != ".." {
|
||||
fullPath := path + "\\" + name
|
||||
isDir := ffd.FileAttributes&windows.FILE_ATTRIBUTE_DIRECTORY != 0 &&
|
||||
ffd.FileAttributes&windows.FILE_ATTRIBUTE_REPARSE_POINT == 0
|
||||
if fn != nil {
|
||||
if err := fn(fullPath, isDir); err != nil {
|
||||
windows.FindClose(hFind)
|
||||
return err
|
||||
}
|
||||
}
|
||||
if isDir && recursive {
|
||||
stack = append(stack, fullPath)
|
||||
}
|
||||
}
|
||||
if err := windows.FindNextFile(hFind, &ffd); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
windows.FindClose(hFind)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user