func kqueue() (kq int, err error) {
	kq, err = unix.Kqueue()
	if kq == -1 {
		return kq, err
	}
	return kq, nil
}
kqueue creates a new kernel event queue and returns a descriptor.
package fsnotify
import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"time"
	"golang.org/x/sys/unix"
)
type Watcher struct {
	Events chan Event
	Errors chan error
	done   chan bool  
	kq int  
	mu              sync.Mutex         
	watches         map[string]int     
	externalWatches map[string]bool    
	dirFlags        map[string]uint32  
	paths           map[int]pathInfo   
	fileExists      map[string]bool    
	isClosed        bool               
}
type pathInfo struct {
	name  string
	isDir bool
}
func NewWatcher() (*Watcher, error) {
	kq, err := kqueue()
	if err != nil {
		return nil, err
	}
	w := &Watcher{
		kq:              kq,
		watches:         make(map[string]int),
		dirFlags:        make(map[string]uint32),
		paths:           make(map[int]pathInfo),
		fileExists:      make(map[string]bool),
		externalWatches: make(map[string]bool),
		Events:          make(chan Event),
		Errors:          make(chan error),
		done:            make(chan bool),
	}
	go w.readEvents()
	return w, nil
}
func (w *Watcher) Close() error {
	w.mu.Lock()
	if w.isClosed {
		w.mu.Unlock()
		return nil
	}
	w.isClosed = true
	w.mu.Unlock()
	w.mu.Lock()
	var pathsToRemove = make([]string, 0, len(w.watches))
	for name := range w.watches {
		pathsToRemove = append(pathsToRemove, name)
	}
	w.mu.Unlock()
	var err error
	for _, name := range pathsToRemove {
		if e := w.Remove(name); e != nil && err == nil {
			err = e
		}
	}
	w.done <- true
	return nil
}
func (w *Watcher) Add(name string) error {
	w.mu.Lock()
	w.externalWatches[name] = true
	w.mu.Unlock()
	_, err := w.addWatch(name, noteAllEvents)
	return err
}
func (w *Watcher) Remove(name string) error {
	name = filepath.Clean(name)
	w.mu.Lock()
	watchfd, ok := w.watches[name]
	w.mu.Unlock()
	if !ok {
		return fmt.Errorf("can't remove non-existent kevent watch for: %s", name)
	}
	const registerRemove = unix.EV_DELETE
	if err := register(w.kq, []int{watchfd}, registerRemove, 0); err != nil {
		return err
	}
	unix.Close(watchfd)
	w.mu.Lock()
	isDir := w.paths[watchfd].isDir
	delete(w.watches, name)
	delete(w.paths, watchfd)
	delete(w.dirFlags, name)
	w.mu.Unlock()
	if isDir {
		var pathsToRemove []string
		w.mu.Lock()
		for _, path := range w.paths {
			wdir, _ := filepath.Split(path.name)
			if filepath.Clean(wdir) == name {
				if !w.externalWatches[path.name] {
					pathsToRemove = append(pathsToRemove, path.name)
				}
			}
		}
		w.mu.Unlock()
		for _, name := range pathsToRemove {
			w.Remove(name)
		}
	}
	return nil
}
const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME
var keventWaitTime = durationToTimespec(100 * time.Millisecond)
func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
	var isDir bool
	name = filepath.Clean(name)
	w.mu.Lock()
	if w.isClosed {
		w.mu.Unlock()
		return "", errors.New("kevent instance already closed")
	}
	watchfd, alreadyWatching := w.watches[name]
	if alreadyWatching {
		isDir = w.paths[watchfd].isDir
	}
	w.mu.Unlock()
	if !alreadyWatching {
		fi, err := os.Lstat(name)
		if err != nil {
			return "", err
		}
		if fi.Mode()&os.ModeSocket == os.ModeSocket {
			return "", nil
		}
		if fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe {
			return "", nil
		}
		if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
			name, err = filepath.EvalSymlinks(name)
			if err != nil {
				return "", nil
			}
			w.mu.Lock()
			_, alreadyWatching = w.watches[name]
			w.mu.Unlock()
			if alreadyWatching {
				return name, nil
			}
			fi, err = os.Lstat(name)
			if err != nil {
				return "", nil
			}
		}
		watchfd, err = unix.Open(name, openMode, 0700)
		if watchfd == -1 {
			return "", err
		}
		isDir = fi.IsDir()
	}
	const registerAdd = unix.EV_ADD | unix.EV_CLEAR | unix.EV_ENABLE
	if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil {
		unix.Close(watchfd)
		return "", err
	}
	if !alreadyWatching {
		w.mu.Lock()
		w.watches[name] = watchfd
		w.paths[watchfd] = pathInfo{name: name, isDir: isDir}
		w.mu.Unlock()
	}
	if isDir {
		w.mu.Lock()
		watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE &&
			(!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE)
		w.dirFlags[name] = flags
		w.mu.Unlock()
		if watchDir {
			if err := w.watchDirectoryFiles(name); err != nil {
				return "", err
			}
		}
	}
	return name, nil
}
func (w *Watcher) readEvents() {
	eventBuffer := make([]unix.Kevent_t, 10)
	for {
		select {
		case <-w.done:
			err := unix.Close(w.kq)
			if err != nil {
				w.Errors <- err
			}
			close(w.Events)
			close(w.Errors)
			return
		default:
		}
		kevents, err := read(w.kq, eventBuffer, &keventWaitTime)
		if err != nil && err != unix.EINTR {
			w.Errors <- err
			continue
		}
		for len(kevents) > 0 {
			kevent := &kevents[0]
			watchfd := int(kevent.Ident)
			mask := uint32(kevent.Fflags)
			w.mu.Lock()
			path := w.paths[watchfd]
			w.mu.Unlock()
			event := newEvent(path.name, mask)
			if path.isDir && !(event.Op&Remove == Remove) {
				if _, err := os.Lstat(event.Name); os.IsNotExist(err) {
					event.Op |= Remove
				}
			}
			if event.Op&Rename == Rename || event.Op&Remove == Remove {
				w.Remove(event.Name)
				w.mu.Lock()
				delete(w.fileExists, event.Name)
				w.mu.Unlock()
			}
			if path.isDir && event.Op&Write == Write && !(event.Op&Remove == Remove) {
				w.sendDirectoryChangeEvents(event.Name)
			} else {
				w.Events <- event
			}
			if event.Op&Remove == Remove {
				if path.isDir {
					fileDir := filepath.Clean(event.Name)
					w.mu.Lock()
					_, found := w.watches[fileDir]
					w.mu.Unlock()
					if found {
						if _, err := os.Lstat(fileDir); err == nil {
							w.sendDirectoryChangeEvents(fileDir)
						}
					}
				} else {
					filePath := filepath.Clean(event.Name)
					if fileInfo, err := os.Lstat(filePath); err == nil {
						w.sendFileCreatedEventIfNew(filePath, fileInfo)
					}
				}
			}
			kevents = kevents[1:]
		}
	}
}
func newEvent(name string, mask uint32) Event {
	e := Event{Name: name}
	if mask&unix.NOTE_DELETE == unix.NOTE_DELETE {
		e.Op |= Remove
	}
	if mask&unix.NOTE_WRITE == unix.NOTE_WRITE {
		e.Op |= Write
	}
	if mask&unix.NOTE_RENAME == unix.NOTE_RENAME {
		e.Op |= Rename
	}
	if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB {
		e.Op |= Chmod
	}
	return e
}
func newCreateEvent(name string) Event {
	return Event{Name: name, Op: Create}
}
func (w *Watcher) watchDirectoryFiles(dirPath string) error {
	files, err := ioutil.ReadDir(dirPath)
	if err != nil {
		return err
	}
	for _, fileInfo := range files {
		filePath := filepath.Join(dirPath, fileInfo.Name())
		filePath, err = w.internalWatch(filePath, fileInfo)
		if err != nil {
			return err
		}
		w.mu.Lock()
		w.fileExists[filePath] = true
		w.mu.Unlock()
	}
	return nil
}
func (w *Watcher) sendDirectoryChangeEvents(dirPath string) {
	files, err := ioutil.ReadDir(dirPath)
	if err != nil {
		w.Errors <- err
	}
	for _, fileInfo := range files {
		filePath := filepath.Join(dirPath, fileInfo.Name())
		err := w.sendFileCreatedEventIfNew(filePath, fileInfo)
		if err != nil {
			return
		}
	}
}
func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) {
	w.mu.Lock()
	_, doesExist := w.fileExists[filePath]
	w.mu.Unlock()
	if !doesExist {
		w.Events <- newCreateEvent(filePath)
	}
	filePath, err = w.internalWatch(filePath, fileInfo)
	if err != nil {
		return err
	}
	w.mu.Lock()
	w.fileExists[filePath] = true
	w.mu.Unlock()
	return nil
}
func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) {
	if fileInfo.IsDir() {
		w.mu.Lock()
		flags := w.dirFlags[name]
		w.mu.Unlock()
		flags |= unix.NOTE_DELETE | unix.NOTE_RENAME
		return w.addWatch(name, flags)
	}
	return w.addWatch(name, noteAllEvents)
}