]>
Commit | Line | Data |
---|---|---|
15c0b25d AP |
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 aix darwin dragonfly freebsd linux netbsd openbsd solaris | |
6 | ||
7 | package unix | |
8 | ||
9 | import ( | |
10 | "bytes" | |
15c0b25d AP |
11 | "sort" |
12 | "sync" | |
13 | "syscall" | |
14 | "unsafe" | |
15 | ) | |
16 | ||
17 | var ( | |
18 | Stdin = 0 | |
19 | Stdout = 1 | |
20 | Stderr = 2 | |
21 | ) | |
22 | ||
15c0b25d AP |
23 | // Do the interface allocations only once for common |
24 | // Errno values. | |
25 | var ( | |
26 | errEAGAIN error = syscall.EAGAIN | |
27 | errEINVAL error = syscall.EINVAL | |
28 | errENOENT error = syscall.ENOENT | |
29 | ) | |
30 | ||
107c1cdb ND |
31 | var ( |
32 | signalNameMapOnce sync.Once | |
33 | signalNameMap map[string]syscall.Signal | |
34 | ) | |
35 | ||
15c0b25d AP |
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 | // ErrnoName returns the error name for error number e. | |
53 | func ErrnoName(e syscall.Errno) string { | |
54 | i := sort.Search(len(errorList), func(i int) bool { | |
55 | return errorList[i].num >= e | |
56 | }) | |
57 | if i < len(errorList) && errorList[i].num == e { | |
58 | return errorList[i].name | |
59 | } | |
60 | return "" | |
61 | } | |
62 | ||
63 | // SignalName returns the signal name for signal number s. | |
64 | func SignalName(s syscall.Signal) string { | |
65 | i := sort.Search(len(signalList), func(i int) bool { | |
66 | return signalList[i].num >= s | |
67 | }) | |
68 | if i < len(signalList) && signalList[i].num == s { | |
69 | return signalList[i].name | |
70 | } | |
71 | return "" | |
72 | } | |
73 | ||
107c1cdb ND |
74 | // SignalNum returns the syscall.Signal for signal named s, |
75 | // or 0 if a signal with such name is not found. | |
76 | // The signal name should start with "SIG". | |
77 | func SignalNum(s string) syscall.Signal { | |
78 | signalNameMapOnce.Do(func() { | |
79 | signalNameMap = make(map[string]syscall.Signal) | |
80 | for _, signal := range signalList { | |
81 | signalNameMap[signal.name] = signal.num | |
82 | } | |
83 | }) | |
84 | return signalNameMap[s] | |
85 | } | |
86 | ||
15c0b25d AP |
87 | // clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte. |
88 | func clen(n []byte) int { | |
89 | i := bytes.IndexByte(n, 0) | |
90 | if i == -1 { | |
91 | i = len(n) | |
92 | } | |
93 | return i | |
94 | } | |
95 | ||
96 | // Mmap manager, for use by operating system-specific implementations. | |
97 | ||
98 | type mmapper struct { | |
99 | sync.Mutex | |
100 | active map[*byte][]byte // active mappings; key is last byte in mapping | |
101 | mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error) | |
102 | munmap func(addr uintptr, length uintptr) error | |
103 | } | |
104 | ||
105 | func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { | |
106 | if length <= 0 { | |
107 | return nil, EINVAL | |
108 | } | |
109 | ||
110 | // Map the requested memory. | |
111 | addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset) | |
112 | if errno != nil { | |
113 | return nil, errno | |
114 | } | |
115 | ||
116 | // Slice memory layout | |
117 | var sl = struct { | |
118 | addr uintptr | |
119 | len int | |
120 | cap int | |
121 | }{addr, length, length} | |
122 | ||
123 | // Use unsafe to turn sl into a []byte. | |
124 | b := *(*[]byte)(unsafe.Pointer(&sl)) | |
125 | ||
126 | // Register mapping in m and return it. | |
127 | p := &b[cap(b)-1] | |
128 | m.Lock() | |
129 | defer m.Unlock() | |
130 | m.active[p] = b | |
131 | return b, nil | |
132 | } | |
133 | ||
134 | func (m *mmapper) Munmap(data []byte) (err error) { | |
135 | if len(data) == 0 || len(data) != cap(data) { | |
136 | return EINVAL | |
137 | } | |
138 | ||
139 | // Find the base of the mapping. | |
140 | p := &data[cap(data)-1] | |
141 | m.Lock() | |
142 | defer m.Unlock() | |
143 | b := m.active[p] | |
144 | if b == nil || &b[0] != &data[0] { | |
145 | return EINVAL | |
146 | } | |
147 | ||
148 | // Unmap the memory and update m. | |
149 | if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil { | |
150 | return errno | |
151 | } | |
152 | delete(m.active, p) | |
153 | return nil | |
154 | } | |
155 | ||
156 | func Read(fd int, p []byte) (n int, err error) { | |
157 | n, err = read(fd, p) | |
158 | if raceenabled { | |
159 | if n > 0 { | |
160 | raceWriteRange(unsafe.Pointer(&p[0]), n) | |
161 | } | |
162 | if err == nil { | |
163 | raceAcquire(unsafe.Pointer(&ioSync)) | |
164 | } | |
165 | } | |
166 | return | |
167 | } | |
168 | ||
169 | func Write(fd int, p []byte) (n int, err error) { | |
170 | if raceenabled { | |
171 | raceReleaseMerge(unsafe.Pointer(&ioSync)) | |
172 | } | |
173 | n, err = write(fd, p) | |
174 | if raceenabled && n > 0 { | |
175 | raceReadRange(unsafe.Pointer(&p[0]), n) | |
176 | } | |
177 | return | |
178 | } | |
179 | ||
180 | // For testing: clients can set this flag to force | |
181 | // creation of IPv6 sockets to return EAFNOSUPPORT. | |
182 | var SocketDisableIPv6 bool | |
183 | ||
184 | // Sockaddr represents a socket address. | |
185 | type Sockaddr interface { | |
186 | sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs | |
187 | } | |
188 | ||
189 | // SockaddrInet4 implements the Sockaddr interface for AF_INET type sockets. | |
190 | type SockaddrInet4 struct { | |
191 | Port int | |
192 | Addr [4]byte | |
193 | raw RawSockaddrInet4 | |
194 | } | |
195 | ||
196 | // SockaddrInet6 implements the Sockaddr interface for AF_INET6 type sockets. | |
197 | type SockaddrInet6 struct { | |
198 | Port int | |
199 | ZoneId uint32 | |
200 | Addr [16]byte | |
201 | raw RawSockaddrInet6 | |
202 | } | |
203 | ||
204 | // SockaddrUnix implements the Sockaddr interface for AF_UNIX type sockets. | |
205 | type SockaddrUnix struct { | |
206 | Name string | |
207 | raw RawSockaddrUnix | |
208 | } | |
209 | ||
210 | func Bind(fd int, sa Sockaddr) (err error) { | |
211 | ptr, n, err := sa.sockaddr() | |
212 | if err != nil { | |
213 | return err | |
214 | } | |
215 | return bind(fd, ptr, n) | |
216 | } | |
217 | ||
218 | func Connect(fd int, sa Sockaddr) (err error) { | |
219 | ptr, n, err := sa.sockaddr() | |
220 | if err != nil { | |
221 | return err | |
222 | } | |
223 | return connect(fd, ptr, n) | |
224 | } | |
225 | ||
226 | func Getpeername(fd int) (sa Sockaddr, err error) { | |
227 | var rsa RawSockaddrAny | |
228 | var len _Socklen = SizeofSockaddrAny | |
229 | if err = getpeername(fd, &rsa, &len); err != nil { | |
230 | return | |
231 | } | |
232 | return anyToSockaddr(fd, &rsa) | |
233 | } | |
234 | ||
235 | func GetsockoptByte(fd, level, opt int) (value byte, err error) { | |
236 | var n byte | |
237 | vallen := _Socklen(1) | |
238 | err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) | |
239 | return n, err | |
240 | } | |
241 | ||
242 | func GetsockoptInt(fd, level, opt int) (value int, err error) { | |
243 | var n int32 | |
244 | vallen := _Socklen(4) | |
245 | err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) | |
246 | return int(n), err | |
247 | } | |
248 | ||
249 | func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) { | |
250 | vallen := _Socklen(4) | |
251 | err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) | |
252 | return value, err | |
253 | } | |
254 | ||
255 | func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) { | |
256 | var value IPMreq | |
257 | vallen := _Socklen(SizeofIPMreq) | |
258 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | |
259 | return &value, err | |
260 | } | |
261 | ||
262 | func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) { | |
263 | var value IPv6Mreq | |
264 | vallen := _Socklen(SizeofIPv6Mreq) | |
265 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | |
266 | return &value, err | |
267 | } | |
268 | ||
269 | func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) { | |
270 | var value IPv6MTUInfo | |
271 | vallen := _Socklen(SizeofIPv6MTUInfo) | |
272 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | |
273 | return &value, err | |
274 | } | |
275 | ||
276 | func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) { | |
277 | var value ICMPv6Filter | |
278 | vallen := _Socklen(SizeofICMPv6Filter) | |
279 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | |
280 | return &value, err | |
281 | } | |
282 | ||
283 | func GetsockoptLinger(fd, level, opt int) (*Linger, error) { | |
284 | var linger Linger | |
285 | vallen := _Socklen(SizeofLinger) | |
286 | err := getsockopt(fd, level, opt, unsafe.Pointer(&linger), &vallen) | |
287 | return &linger, err | |
288 | } | |
289 | ||
290 | func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) { | |
291 | var tv Timeval | |
292 | vallen := _Socklen(unsafe.Sizeof(tv)) | |
293 | err := getsockopt(fd, level, opt, unsafe.Pointer(&tv), &vallen) | |
294 | return &tv, err | |
295 | } | |
296 | ||
107c1cdb ND |
297 | func GetsockoptUint64(fd, level, opt int) (value uint64, err error) { |
298 | var n uint64 | |
299 | vallen := _Socklen(8) | |
300 | err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) | |
301 | return n, err | |
302 | } | |
303 | ||
15c0b25d AP |
304 | func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { |
305 | var rsa RawSockaddrAny | |
306 | var len _Socklen = SizeofSockaddrAny | |
307 | if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil { | |
308 | return | |
309 | } | |
310 | if rsa.Addr.Family != AF_UNSPEC { | |
311 | from, err = anyToSockaddr(fd, &rsa) | |
312 | } | |
313 | return | |
314 | } | |
315 | ||
316 | func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { | |
317 | ptr, n, err := to.sockaddr() | |
318 | if err != nil { | |
319 | return err | |
320 | } | |
321 | return sendto(fd, p, flags, ptr, n) | |
322 | } | |
323 | ||
324 | func SetsockoptByte(fd, level, opt int, value byte) (err error) { | |
325 | return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1) | |
326 | } | |
327 | ||
328 | func SetsockoptInt(fd, level, opt int, value int) (err error) { | |
329 | var n = int32(value) | |
330 | return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4) | |
331 | } | |
332 | ||
333 | func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) { | |
334 | return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4) | |
335 | } | |
336 | ||
337 | func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) { | |
338 | return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq) | |
339 | } | |
340 | ||
341 | func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) { | |
342 | return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq) | |
343 | } | |
344 | ||
345 | func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error { | |
346 | return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter) | |
347 | } | |
348 | ||
349 | func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) { | |
350 | return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger) | |
351 | } | |
352 | ||
353 | func SetsockoptString(fd, level, opt int, s string) (err error) { | |
107c1cdb ND |
354 | var p unsafe.Pointer |
355 | if len(s) > 0 { | |
356 | p = unsafe.Pointer(&[]byte(s)[0]) | |
357 | } | |
358 | return setsockopt(fd, level, opt, p, uintptr(len(s))) | |
15c0b25d AP |
359 | } |
360 | ||
361 | func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) { | |
362 | return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv)) | |
363 | } | |
364 | ||
107c1cdb ND |
365 | func SetsockoptUint64(fd, level, opt int, value uint64) (err error) { |
366 | return setsockopt(fd, level, opt, unsafe.Pointer(&value), 8) | |
367 | } | |
368 | ||
15c0b25d AP |
369 | func Socket(domain, typ, proto int) (fd int, err error) { |
370 | if domain == AF_INET6 && SocketDisableIPv6 { | |
371 | return -1, EAFNOSUPPORT | |
372 | } | |
373 | fd, err = socket(domain, typ, proto) | |
374 | return | |
375 | } | |
376 | ||
377 | func Socketpair(domain, typ, proto int) (fd [2]int, err error) { | |
378 | var fdx [2]int32 | |
379 | err = socketpair(domain, typ, proto, &fdx) | |
380 | if err == nil { | |
381 | fd[0] = int(fdx[0]) | |
382 | fd[1] = int(fdx[1]) | |
383 | } | |
384 | return | |
385 | } | |
386 | ||
15c0b25d AP |
387 | var ioSync int64 |
388 | ||
389 | func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) } | |
390 | ||
391 | func SetNonblock(fd int, nonblocking bool) (err error) { | |
392 | flag, err := fcntl(fd, F_GETFL, 0) | |
393 | if err != nil { | |
394 | return err | |
395 | } | |
396 | if nonblocking { | |
397 | flag |= O_NONBLOCK | |
398 | } else { | |
399 | flag &= ^O_NONBLOCK | |
400 | } | |
401 | _, err = fcntl(fd, F_SETFL, flag) | |
402 | return err | |
403 | } | |
404 | ||
405 | // Exec calls execve(2), which replaces the calling executable in the process | |
406 | // tree. argv0 should be the full path to an executable ("/bin/ls") and the | |
407 | // executable name should also be the first argument in argv (["ls", "-l"]). | |
408 | // envv are the environment variables that should be passed to the new | |
409 | // process (["USER=go", "PWD=/tmp"]). | |
410 | func Exec(argv0 string, argv []string, envv []string) error { | |
411 | return syscall.Exec(argv0, argv, envv) | |
412 | } | |
107c1cdb ND |
413 | |
414 | // Lutimes sets the access and modification times tv on path. If path refers to | |
415 | // a symlink, it is not dereferenced and the timestamps are set on the symlink. | |
416 | // If tv is nil, the access and modification times are set to the current time. | |
417 | // Otherwise tv must contain exactly 2 elements, with access time as the first | |
418 | // element and modification time as the second element. | |
419 | func Lutimes(path string, tv []Timeval) error { | |
420 | if tv == nil { | |
421 | return UtimesNanoAt(AT_FDCWD, path, nil, AT_SYMLINK_NOFOLLOW) | |
422 | } | |
423 | if len(tv) != 2 { | |
424 | return EINVAL | |
425 | } | |
426 | ts := []Timespec{ | |
427 | NsecToTimespec(TimevalToNsec(tv[0])), | |
428 | NsecToTimespec(TimevalToNsec(tv[1])), | |
429 | } | |
430 | return UtimesNanoAt(AT_FDCWD, path, ts, AT_SYMLINK_NOFOLLOW) | |
431 | } |