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