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