OSDN Git Service

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