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