]>
Commit | Line | Data |
---|---|---|
9b12e4fe JC |
1 | // Copyright 2009 The Go Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style | |
3 | // license that can be found in the LICENSE file. | |
4 | ||
5 | // +build darwin dragonfly freebsd linux netbsd openbsd solaris | |
6 | ||
7 | package unix | |
8 | ||
9 | import ( | |
10 | "runtime" | |
11 | "sync" | |
12 | "syscall" | |
13 | "unsafe" | |
14 | ) | |
15 | ||
16 | var ( | |
17 | Stdin = 0 | |
18 | Stdout = 1 | |
19 | Stderr = 2 | |
20 | ) | |
21 | ||
22 | const ( | |
23 | darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8 | |
24 | dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8 | |
25 | netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4 | |
26 | ) | |
27 | ||
28 | // Do the interface allocations only once for common | |
29 | // Errno values. | |
30 | var ( | |
31 | errEAGAIN error = syscall.EAGAIN | |
32 | errEINVAL error = syscall.EINVAL | |
33 | errENOENT error = syscall.ENOENT | |
34 | ) | |
35 | ||
36 | // errnoErr returns common boxed Errno values, to prevent | |
37 | // allocations at runtime. | |
38 | func errnoErr(e syscall.Errno) error { | |
39 | switch e { | |
40 | case 0: | |
41 | return nil | |
42 | case EAGAIN: | |
43 | return errEAGAIN | |
44 | case EINVAL: | |
45 | return errEINVAL | |
46 | case ENOENT: | |
47 | return errENOENT | |
48 | } | |
49 | return e | |
50 | } | |
51 | ||
52 | func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) | |
53 | func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) | |
54 | func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) | |
55 | func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) | |
56 | ||
57 | // Mmap manager, for use by operating system-specific implementations. | |
58 | ||
59 | type mmapper struct { | |
60 | sync.Mutex | |
61 | active map[*byte][]byte // active mappings; key is last byte in mapping | |
62 | mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error) | |
63 | munmap func(addr uintptr, length uintptr) error | |
64 | } | |
65 | ||
66 | func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { | |
67 | if length <= 0 { | |
68 | return nil, EINVAL | |
69 | } | |
70 | ||
71 | // Map the requested memory. | |
72 | addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset) | |
73 | if errno != nil { | |
74 | return nil, errno | |
75 | } | |
76 | ||
77 | // Slice memory layout | |
78 | var sl = struct { | |
79 | addr uintptr | |
80 | len int | |
81 | cap int | |
82 | }{addr, length, length} | |
83 | ||
84 | // Use unsafe to turn sl into a []byte. | |
85 | b := *(*[]byte)(unsafe.Pointer(&sl)) | |
86 | ||
87 | // Register mapping in m and return it. | |
88 | p := &b[cap(b)-1] | |
89 | m.Lock() | |
90 | defer m.Unlock() | |
91 | m.active[p] = b | |
92 | return b, nil | |
93 | } | |
94 | ||
95 | func (m *mmapper) Munmap(data []byte) (err error) { | |
96 | if len(data) == 0 || len(data) != cap(data) { | |
97 | return EINVAL | |
98 | } | |
99 | ||
100 | // Find the base of the mapping. | |
101 | p := &data[cap(data)-1] | |
102 | m.Lock() | |
103 | defer m.Unlock() | |
104 | b := m.active[p] | |
105 | if b == nil || &b[0] != &data[0] { | |
106 | return EINVAL | |
107 | } | |
108 | ||
109 | // Unmap the memory and update m. | |
110 | if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil { | |
111 | return errno | |
112 | } | |
113 | delete(m.active, p) | |
114 | return nil | |
115 | } | |
116 | ||
117 | func Read(fd int, p []byte) (n int, err error) { | |
118 | n, err = read(fd, p) | |
119 | if raceenabled { | |
120 | if n > 0 { | |
121 | raceWriteRange(unsafe.Pointer(&p[0]), n) | |
122 | } | |
123 | if err == nil { | |
124 | raceAcquire(unsafe.Pointer(&ioSync)) | |
125 | } | |
126 | } | |
127 | return | |
128 | } | |
129 | ||
130 | func Write(fd int, p []byte) (n int, err error) { | |
131 | if raceenabled { | |
132 | raceReleaseMerge(unsafe.Pointer(&ioSync)) | |
133 | } | |
134 | n, err = write(fd, p) | |
135 | if raceenabled && n > 0 { | |
136 | raceReadRange(unsafe.Pointer(&p[0]), n) | |
137 | } | |
138 | return | |
139 | } | |
140 | ||
141 | // For testing: clients can set this flag to force | |
142 | // creation of IPv6 sockets to return EAFNOSUPPORT. | |
143 | var SocketDisableIPv6 bool | |
144 | ||
145 | type Sockaddr interface { | |
146 | sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs | |
147 | } | |
148 | ||
149 | type SockaddrInet4 struct { | |
150 | Port int | |
151 | Addr [4]byte | |
152 | raw RawSockaddrInet4 | |
153 | } | |
154 | ||
155 | type SockaddrInet6 struct { | |
156 | Port int | |
157 | ZoneId uint32 | |
158 | Addr [16]byte | |
159 | raw RawSockaddrInet6 | |
160 | } | |
161 | ||
162 | type SockaddrUnix struct { | |
163 | Name string | |
164 | raw RawSockaddrUnix | |
165 | } | |
166 | ||
167 | func Bind(fd int, sa Sockaddr) (err error) { | |
168 | ptr, n, err := sa.sockaddr() | |
169 | if err != nil { | |
170 | return err | |
171 | } | |
172 | return bind(fd, ptr, n) | |
173 | } | |
174 | ||
175 | func Connect(fd int, sa Sockaddr) (err error) { | |
176 | ptr, n, err := sa.sockaddr() | |
177 | if err != nil { | |
178 | return err | |
179 | } | |
180 | return connect(fd, ptr, n) | |
181 | } | |
182 | ||
183 | func Getpeername(fd int) (sa Sockaddr, err error) { | |
184 | var rsa RawSockaddrAny | |
185 | var len _Socklen = SizeofSockaddrAny | |
186 | if err = getpeername(fd, &rsa, &len); err != nil { | |
187 | return | |
188 | } | |
189 | return anyToSockaddr(&rsa) | |
190 | } | |
191 | ||
192 | func GetsockoptInt(fd, level, opt int) (value int, err error) { | |
193 | var n int32 | |
194 | vallen := _Socklen(4) | |
195 | err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) | |
196 | return int(n), err | |
197 | } | |
198 | ||
199 | func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { | |
200 | var rsa RawSockaddrAny | |
201 | var len _Socklen = SizeofSockaddrAny | |
202 | if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil { | |
203 | return | |
204 | } | |
205 | if rsa.Addr.Family != AF_UNSPEC { | |
206 | from, err = anyToSockaddr(&rsa) | |
207 | } | |
208 | return | |
209 | } | |
210 | ||
211 | func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { | |
212 | ptr, n, err := to.sockaddr() | |
213 | if err != nil { | |
214 | return err | |
215 | } | |
216 | return sendto(fd, p, flags, ptr, n) | |
217 | } | |
218 | ||
219 | func SetsockoptByte(fd, level, opt int, value byte) (err error) { | |
220 | return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1) | |
221 | } | |
222 | ||
223 | func SetsockoptInt(fd, level, opt int, value int) (err error) { | |
224 | var n = int32(value) | |
225 | return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4) | |
226 | } | |
227 | ||
228 | func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) { | |
229 | return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4) | |
230 | } | |
231 | ||
232 | func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) { | |
233 | return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq) | |
234 | } | |
235 | ||
236 | func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) { | |
237 | return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq) | |
238 | } | |
239 | ||
240 | func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error { | |
241 | return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter) | |
242 | } | |
243 | ||
244 | func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) { | |
245 | return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger) | |
246 | } | |
247 | ||
248 | func SetsockoptString(fd, level, opt int, s string) (err error) { | |
249 | return setsockopt(fd, level, opt, unsafe.Pointer(&[]byte(s)[0]), uintptr(len(s))) | |
250 | } | |
251 | ||
252 | func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) { | |
253 | return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv)) | |
254 | } | |
255 | ||
256 | func Socket(domain, typ, proto int) (fd int, err error) { | |
257 | if domain == AF_INET6 && SocketDisableIPv6 { | |
258 | return -1, EAFNOSUPPORT | |
259 | } | |
260 | fd, err = socket(domain, typ, proto) | |
261 | return | |
262 | } | |
263 | ||
264 | func Socketpair(domain, typ, proto int) (fd [2]int, err error) { | |
265 | var fdx [2]int32 | |
266 | err = socketpair(domain, typ, proto, &fdx) | |
267 | if err == nil { | |
268 | fd[0] = int(fdx[0]) | |
269 | fd[1] = int(fdx[1]) | |
270 | } | |
271 | return | |
272 | } | |
273 | ||
274 | func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { | |
275 | if raceenabled { | |
276 | raceReleaseMerge(unsafe.Pointer(&ioSync)) | |
277 | } | |
278 | return sendfile(outfd, infd, offset, count) | |
279 | } | |
280 | ||
281 | var ioSync int64 | |
282 | ||
283 | func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) } | |
284 | ||
285 | func SetNonblock(fd int, nonblocking bool) (err error) { | |
286 | flag, err := fcntl(fd, F_GETFL, 0) | |
287 | if err != nil { | |
288 | return err | |
289 | } | |
290 | if nonblocking { | |
291 | flag |= O_NONBLOCK | |
292 | } else { | |
293 | flag &= ^O_NONBLOCK | |
294 | } | |
295 | _, err = fcntl(fd, F_SETFL, flag) | |
296 | return err | |
297 | } |