blob: a06bd7dd083252ee1fc70bd9bbbabe5dce8c6b01 [file] [log] [blame]
Alex Brainman64f33882010-03-19 15:21:37 -07001// 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
Aram Hăvărneanu1c986192014-02-25 21:12:10 +11005// +build darwin dragonfly freebsd linux netbsd openbsd solaris
Russ Cox27159562011-09-15 16:48:57 -04006
Alex Brainman64f33882010-03-19 15:21:37 -07007package syscall
8
Yuval Pavel Zholkover400d8252011-06-14 11:29:51 -04009import (
Mikio Hara92c8df42012-01-14 06:40:55 +090010 "runtime"
Yuval Pavel Zholkover400d8252011-06-14 11:29:51 -040011 "sync"
12 "unsafe"
13)
14
Alex Brainman79017aa2010-04-02 01:11:17 -070015var (
16 Stdin = 0
17 Stdout = 1
18 Stderr = 2
19)
20
Mikio Hara9a794722013-08-25 08:44:31 +090021const (
Mikio Harad844d692014-04-27 22:28:41 +090022 darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8
23 dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
24 netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4
Mikio Hara9a794722013-08-25 08:44:31 +090025)
Mikio Hara5d6f1182011-06-20 18:40:20 -040026
Russ Coxc017a822011-11-13 22:44:52 -050027func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
28func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
29func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
30func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
Yuval Pavel Zholkover400d8252011-06-14 11:29:51 -040031
32// Mmap manager, for use by operating system-specific implementations.
33
34type mmapper struct {
35 sync.Mutex
36 active map[*byte][]byte // active mappings; key is last byte in mapping
Russ Coxc017a822011-11-13 22:44:52 -050037 mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
38 munmap func(addr uintptr, length uintptr) error
Yuval Pavel Zholkover400d8252011-06-14 11:29:51 -040039}
40
Russ Coxc017a822011-11-13 22:44:52 -050041func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
Yuval Pavel Zholkover400d8252011-06-14 11:29:51 -040042 if length <= 0 {
43 return nil, EINVAL
44 }
45
46 // Map the requested memory.
47 addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
Russ Coxc017a822011-11-13 22:44:52 -050048 if errno != nil {
Yuval Pavel Zholkover400d8252011-06-14 11:29:51 -040049 return nil, errno
50 }
51
52 // Slice memory layout
53 var sl = struct {
54 addr uintptr
55 len int
56 cap int
57 }{addr, length, length}
58
Ian Lance Taylorae558582014-08-04 20:30:26 -070059 // Use unsafe to turn sl into a []byte.
Yuval Pavel Zholkover400d8252011-06-14 11:29:51 -040060 b := *(*[]byte)(unsafe.Pointer(&sl))
61
62 // Register mapping in m and return it.
63 p := &b[cap(b)-1]
64 m.Lock()
65 defer m.Unlock()
66 m.active[p] = b
Russ Coxc017a822011-11-13 22:44:52 -050067 return b, nil
Yuval Pavel Zholkover400d8252011-06-14 11:29:51 -040068}
69
Russ Coxc017a822011-11-13 22:44:52 -050070func (m *mmapper) Munmap(data []byte) (err error) {
Yuval Pavel Zholkover400d8252011-06-14 11:29:51 -040071 if len(data) == 0 || len(data) != cap(data) {
72 return EINVAL
73 }
74
75 // Find the base of the mapping.
76 p := &data[cap(data)-1]
77 m.Lock()
78 defer m.Unlock()
79 b := m.active[p]
80 if b == nil || &b[0] != &data[0] {
81 return EINVAL
82 }
83
84 // Unmap the memory and update m.
Russ Coxc017a822011-11-13 22:44:52 -050085 if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
Yuval Pavel Zholkover400d8252011-06-14 11:29:51 -040086 return errno
87 }
Russ Cox313c8222011-10-18 09:56:34 -040088 delete(m.active, p)
Russ Coxc017a822011-11-13 22:44:52 -050089 return nil
90}
91
92// An Errno is an unsigned number describing an error condition.
93// It implements the error interface. The zero Errno is by convention
94// a non-error, so code to convert from Errno to error should use:
95// err = nil
96// if errno != 0 {
97// err = errno
98// }
99type Errno uintptr
100
101func (e Errno) Error() string {
Russ Cox014568be2012-02-16 15:23:50 -0500102 if 0 <= int(e) && int(e) < len(errors) {
Russ Coxc017a822011-11-13 22:44:52 -0500103 s := errors[e]
104 if s != "" {
105 return s
106 }
107 }
108 return "errno " + itoa(int(e))
109}
110
111func (e Errno) Temporary() bool {
Russ Coxa07a57b2014-09-18 23:07:36 -0400112 return e == EINTR || e == EMFILE || e == ECONNRESET || e == ECONNABORTED || e.Timeout()
Russ Coxc017a822011-11-13 22:44:52 -0500113}
114
115func (e Errno) Timeout() bool {
116 return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
Yuval Pavel Zholkover400d8252011-06-14 11:29:51 -0400117}
Russ Cox35586f72012-02-13 13:52:37 -0500118
119// A Signal is a number describing a process signal.
120// It implements the os.Signal interface.
121type Signal int
122
123func (s Signal) Signal() {}
124
125func (s Signal) String() string {
126 if 0 <= s && int(s) < len(signals) {
127 str := signals[s]
128 if str != "" {
129 return str
130 }
131 }
132 return "signal " + itoa(int(s))
133}
Dmitriy Vyukovcffbfae2012-10-09 20:51:58 +0400134
135func Read(fd int, p []byte) (n int, err error) {
136 n, err = read(fd, p)
Dmitriy Vyukovfc807642013-06-10 22:40:35 +0400137 if raceenabled {
138 if n > 0 {
139 raceWriteRange(unsafe.Pointer(&p[0]), n)
140 }
141 if err == nil {
142 raceAcquire(unsafe.Pointer(&ioSync))
143 }
Dmitriy Vyukovcffbfae2012-10-09 20:51:58 +0400144 }
145 return
146}
147
148func Write(fd int, p []byte) (n int, err error) {
149 if raceenabled {
150 raceReleaseMerge(unsafe.Pointer(&ioSync))
151 }
Dmitriy Vyukovfc807642013-06-10 22:40:35 +0400152 n, err = write(fd, p)
153 if raceenabled && n > 0 {
154 raceReadRange(unsafe.Pointer(&p[0]), n)
155 }
156 return
Dmitriy Vyukovcffbfae2012-10-09 20:51:58 +0400157}
158
Dave Cheneydd3a3cf2013-06-22 11:03:40 +1000159// For testing: clients can set this flag to force
160// creation of IPv6 sockets to return EAFNOSUPPORT.
161var SocketDisableIPv6 bool
162
163type Sockaddr interface {
Brad Fitzpatrickf00af3d2014-01-21 18:54:49 -0800164 sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs
Dave Cheneydd3a3cf2013-06-22 11:03:40 +1000165}
166
167type SockaddrInet4 struct {
168 Port int
169 Addr [4]byte
170 raw RawSockaddrInet4
171}
172
173type SockaddrInet6 struct {
174 Port int
175 ZoneId uint32
176 Addr [16]byte
177 raw RawSockaddrInet6
178}
179
180type SockaddrUnix struct {
181 Name string
182 raw RawSockaddrUnix
183}
184
185func Bind(fd int, sa Sockaddr) (err error) {
186 ptr, n, err := sa.sockaddr()
187 if err != nil {
188 return err
189 }
190 return bind(fd, ptr, n)
191}
192
193func Connect(fd int, sa Sockaddr) (err error) {
194 ptr, n, err := sa.sockaddr()
195 if err != nil {
196 return err
197 }
198 return connect(fd, ptr, n)
199}
200
Dave Cheney3b76d702013-06-25 10:14:40 +1000201func Getpeername(fd int) (sa Sockaddr, err error) {
202 var rsa RawSockaddrAny
203 var len _Socklen = SizeofSockaddrAny
204 if err = getpeername(fd, &rsa, &len); err != nil {
205 return
206 }
207 return anyToSockaddr(&rsa)
208}
209
Mikio Hara678ba852014-07-30 10:02:16 +0900210func GetsockoptInt(fd, level, opt int) (value int, err error) {
211 var n int32
212 vallen := _Socklen(4)
213 err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
214 return int(n), err
215}
216
Dave Cheney3b76d702013-06-25 10:14:40 +1000217func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
218 var rsa RawSockaddrAny
219 var len _Socklen = SizeofSockaddrAny
220 if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
221 return
222 }
223 if rsa.Addr.Family != AF_UNSPEC {
224 from, err = anyToSockaddr(&rsa)
225 }
226 return
227}
228
229func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
230 ptr, n, err := to.sockaddr()
231 if err != nil {
232 return err
233 }
234 return sendto(fd, p, flags, ptr, n)
235}
236
Mikio Hara678ba852014-07-30 10:02:16 +0900237func SetsockoptByte(fd, level, opt int, value byte) (err error) {
Brad Fitzpatrickf00af3d2014-01-21 18:54:49 -0800238 return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
Dave Cheney2a730f82013-07-05 13:25:23 +1000239}
240
Mikio Hara678ba852014-07-30 10:02:16 +0900241func SetsockoptInt(fd, level, opt int, value int) (err error) {
242 var n = int32(value)
Brad Fitzpatrickf00af3d2014-01-21 18:54:49 -0800243 return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
Dave Cheney2a730f82013-07-05 13:25:23 +1000244}
245
Mikio Hara678ba852014-07-30 10:02:16 +0900246func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
Brad Fitzpatrickf00af3d2014-01-21 18:54:49 -0800247 return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
Dave Cheney2a730f82013-07-05 13:25:23 +1000248}
249
Mikio Hara678ba852014-07-30 10:02:16 +0900250func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
Brad Fitzpatrickf00af3d2014-01-21 18:54:49 -0800251 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq)
Dave Cheney2a730f82013-07-05 13:25:23 +1000252}
253
Mikio Hara678ba852014-07-30 10:02:16 +0900254func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
Brad Fitzpatrickf00af3d2014-01-21 18:54:49 -0800255 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq)
Dave Cheney2a730f82013-07-05 13:25:23 +1000256}
257
258func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
Brad Fitzpatrickf00af3d2014-01-21 18:54:49 -0800259 return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
Dave Cheney2a730f82013-07-05 13:25:23 +1000260}
261
Mikio Hara678ba852014-07-30 10:02:16 +0900262func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
Brad Fitzpatrickf00af3d2014-01-21 18:54:49 -0800263 return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger)
Dave Cheney2a730f82013-07-05 13:25:23 +1000264}
265
Mikio Hara678ba852014-07-30 10:02:16 +0900266func SetsockoptString(fd, level, opt int, s string) (err error) {
Brad Fitzpatrickf00af3d2014-01-21 18:54:49 -0800267 return setsockopt(fd, level, opt, unsafe.Pointer(&[]byte(s)[0]), uintptr(len(s)))
Dave Cheney2a730f82013-07-05 13:25:23 +1000268}
269
Mikio Hara678ba852014-07-30 10:02:16 +0900270func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
Brad Fitzpatrickf00af3d2014-01-21 18:54:49 -0800271 return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv))
Dave Cheney2a730f82013-07-05 13:25:23 +1000272}
273
Dave Cheneydd3a3cf2013-06-22 11:03:40 +1000274func Socket(domain, typ, proto int) (fd int, err error) {
275 if domain == AF_INET6 && SocketDisableIPv6 {
276 return -1, EAFNOSUPPORT
277 }
278 fd, err = socket(domain, typ, proto)
279 return
280}
281
282func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
283 var fdx [2]int32
284 err = socketpair(domain, typ, proto, &fdx)
285 if err == nil {
286 fd[0] = int(fdx[0])
287 fd[1] = int(fdx[1])
288 }
289 return
290}
291
Dmitriy Vyukovc242aa32012-10-29 23:15:06 +0400292func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
293 if raceenabled {
294 raceReleaseMerge(unsafe.Pointer(&ioSync))
295 }
296 return sendfile(outfd, infd, offset, count)
297}
298
Dmitriy Vyukovcffbfae2012-10-09 20:51:58 +0400299var ioSync int64