golang
复制代码
package main
import (
"log"
"syscall"
"unsafe"
)
type FileNotifyInformation struct {
Action uint32
Name string
}
func Fswatch(path string) (chan FileNotifyInformation, error) {
handle, err := syscall.CreateFile(
syscall.StringToUTF16Ptr(path),
0x0001,
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
nil,
syscall.OPEN_EXISTING,
syscall.FILE_FLAG_BACKUP_SEMANTICS,
0,
)
if err != nil {
return nil, err
}
c := make(chan FileNotifyInformation, 4)
go func() {
defer syscall.CloseHandle(handle)
defer close(c)
buflen := 1024
buf := make([]byte, buflen)
for {
err := syscall.ReadDirectoryChanges(
handle,
&buf[0],
uint32(buflen),
true,
syscall.FILE_NOTIFY_CHANGE_FILE_NAME|
syscall.FILE_NOTIFY_CHANGE_DIR_NAME|
syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES|
syscall.FILE_NOTIFY_CHANGE_SIZE|
syscall.FILE_NOTIFY_CHANGE_LAST_WRITE,
nil,
&syscall.Overlapped{},
0,
)
if err != nil {
break
}
var offset uint32
for {
raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&buf[offset]))
buf := (*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName))
name := syscall.UTF16ToString(buf[:raw.FileNameLength/2])
info := FileNotifyInformation{
Action: raw.Action,
Name: name,
}
c <- info
if raw.NextEntryOffset == 0 {
break
}
offset += raw.NextEntryOffset
if offset >= 1024 {
break
}
}
}
}()
return c, nil
}
func main() {
c, err := Fswatch("E:\\company")
if err != nil {
log.Fatalln(err)
}
for info := range c {
switch info.Action {
case 1:
log.Println("Create", info.Name)
case 2:
log.Println("Delete", info.Name)
case 3:
log.Println("Update", info.Name)
case 4:
log.Println("RenameFrom", info.Name)
case 5:
log.Println("RenameTo", info.Name)
}
}
}