github.com/DiversionCompany/notify@v0.9.9/watcher_fen_cgo.go (about) 1 // Copyright (c) 2014-2015 The Notify Authors. All rights reserved. 2 // Use of this source code is governed by the MIT license that can be 3 // found in the LICENSE file. 4 5 //go:build solaris || illumos 6 // +build solaris illumos 7 8 package notify 9 10 // #include <port.h> 11 // #include <stdio.h> 12 // #include <stdlib.h> 13 // struct file_obj* newFo() { return (struct file_obj*) malloc(sizeof(struct file_obj)); } 14 // port_event_t* newPe() { return (port_event_t*) malloc(sizeof(port_event_t)); } 15 // uintptr_t conv(struct file_obj* fo) { return (uintptr_t) fo; } 16 // struct file_obj* dconv(uintptr_t fo) { return (struct file_obj*) fo; } 17 import "C" 18 19 import ( 20 "syscall" 21 "unsafe" 22 ) 23 24 const ( 25 fileAccess = Event(C.FILE_ACCESS) 26 fileModified = Event(C.FILE_MODIFIED) 27 fileAttrib = Event(C.FILE_ATTRIB) 28 fileDelete = Event(C.FILE_DELETE) 29 fileRenameTo = Event(C.FILE_RENAME_TO) 30 fileRenameFrom = Event(C.FILE_RENAME_FROM) 31 fileTrunc = Event(C.FILE_TRUNC) 32 fileNoFollow = Event(C.FILE_NOFOLLOW) 33 unmounted = Event(C.UNMOUNTED) 34 mountedOver = Event(C.MOUNTEDOVER) 35 ) 36 37 // PortEvent is a notify's equivalent of port_event_t. 38 type PortEvent struct { 39 PortevEvents int // PortevEvents is an equivalent of portev_events. 40 PortevSource uint8 // PortevSource is an equivalent of portev_source. 41 PortevPad uint8 // Portevpad is an equivalent of portev_pad. 42 PortevObject interface{} // PortevObject is an equivalent of portev_object. 43 PortevUser uintptr // PortevUser is an equivalent of portev_user. 44 } 45 46 // FileObj is a notify's equivalent of file_obj. 47 type FileObj struct { 48 Atim syscall.Timespec // Atim is an equivalent of fo_atime. 49 Mtim syscall.Timespec // Mtim is an equivalent of fo_mtime. 50 Ctim syscall.Timespec // Ctim is an equivalent of fo_ctime. 51 Pad [3]uintptr // Pad is an equivalent of fo_pad. 52 Name string // Name is an equivalent of fo_name. 53 } 54 55 type cfen struct { 56 p2pe map[string]*C.port_event_t 57 p2fo map[string]*C.struct_file_obj 58 } 59 60 func newCfen() cfen { 61 return cfen{ 62 p2pe: make(map[string]*C.port_event_t), 63 p2fo: make(map[string]*C.struct_file_obj), 64 } 65 } 66 67 func unix2C(sec int64, nsec int64) (C.time_t, C.long) { 68 return C.time_t(sec), C.long(nsec) 69 } 70 71 func (c *cfen) portAssociate(p int, fo FileObj, e int) (err error) { 72 cfo := C.newFo() 73 cfo.fo_atime.tv_sec, cfo.fo_atime.tv_nsec = unix2C(fo.Atim.Unix()) 74 cfo.fo_mtime.tv_sec, cfo.fo_mtime.tv_nsec = unix2C(fo.Mtim.Unix()) 75 cfo.fo_ctime.tv_sec, cfo.fo_ctime.tv_nsec = unix2C(fo.Ctim.Unix()) 76 cfo.fo_name = C.CString(fo.Name) 77 c.p2fo[fo.Name] = cfo 78 _, err = C.port_associate(C.int(p), srcFile, C.conv(cfo), C.int(e), nil) 79 return 80 } 81 82 func (c *cfen) portDissociate(port int, fo FileObj) (err error) { 83 cfo, ok := c.p2fo[fo.Name] 84 if !ok { 85 return errNotWatched 86 } 87 _, err = C.port_dissociate(C.int(port), srcFile, C.conv(cfo)) 88 C.free(unsafe.Pointer(cfo.fo_name)) 89 C.free(unsafe.Pointer(cfo)) 90 delete(c.p2fo, fo.Name) 91 return 92 } 93 94 const srcAlert = C.PORT_SOURCE_ALERT 95 const srcFile = C.PORT_SOURCE_FILE 96 const alertSet = C.PORT_ALERT_SET 97 98 func cfo2fo(cfo *C.struct_file_obj) *FileObj { 99 // Currently remaining attributes are not used. 100 if cfo == nil { 101 return nil 102 } 103 var fo FileObj 104 fo.Name = C.GoString(cfo.fo_name) 105 return &fo 106 } 107 108 func (c *cfen) portGet(port int, pe *PortEvent) (err error) { 109 cpe := C.newPe() 110 if _, err = C.port_get(C.int(port), cpe, nil); err != nil { 111 C.free(unsafe.Pointer(cpe)) 112 return 113 } 114 pe.PortevEvents, pe.PortevSource, pe.PortevPad = 115 int(cpe.portev_events), uint8(cpe.portev_source), uint8(cpe.portev_pad) 116 pe.PortevObject = cfo2fo(C.dconv(cpe.portev_object)) 117 pe.PortevUser = uintptr(cpe.portev_user) 118 C.free(unsafe.Pointer(cpe)) 119 return 120 } 121 122 func (c *cfen) portCreate() (int, error) { 123 p, err := C.port_create() 124 return int(p), err 125 } 126 127 func (c *cfen) portAlert(p int) (err error) { 128 _, err = C.port_alert(C.int(p), alertSet, C.int(666), nil) 129 return 130 } 131 132 func (c *cfen) free() { 133 for i := range c.p2fo { 134 C.free(unsafe.Pointer(c.p2fo[i].fo_name)) 135 C.free(unsafe.Pointer(c.p2fo[i])) 136 } 137 for i := range c.p2pe { 138 C.free(unsafe.Pointer(c.p2pe[i])) 139 } 140 c.p2fo = make(map[string]*C.struct_file_obj) 141 c.p2pe = make(map[string]*C.port_event_t) 142 }