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//go:build unix
6
7package syscall
8
9import (
10	errorspkg "errors"
11	"internal/asan"
12	"internal/bytealg"
13	"internal/itoa"
14	"internal/msan"
15	"internal/oserror"
16	"internal/race"
17	"runtime"
18	"sync"
19	"unsafe"
20)
21
22var (
23	Stdin  = 0
24	Stdout = 1
25	Stderr = 2
26)
27
28const (
29	darwin64Bit = (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && sizeofPtr == 8
30	netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4
31)
32
33// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
34func clen(n []byte) int {
35	if i := bytealg.IndexByte(n, 0); i != -1 {
36		return i
37	}
38	return len(n)
39}
40
41// Mmap manager, for use by operating system-specific implementations.
42
43type mmapper struct {
44	sync.Mutex
45	active map[*byte][]byte // active mappings; key is last byte in mapping
46	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
47	munmap func(addr uintptr, length uintptr) error
48}
49
50func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
51	if length <= 0 {
52		return nil, EINVAL
53	}
54
55	// Map the requested memory.
56	addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
57	if errno != nil {
58		return nil, errno
59	}
60
61	// Use unsafe to turn addr into a []byte.
62	b := unsafe.Slice((*byte)(unsafe.Pointer(addr)), length)
63
64	// Register mapping in m and return it.
65	p := &b[cap(b)-1]
66	m.Lock()
67	defer m.Unlock()
68	m.active[p] = b
69	return b, nil
70}
71
72func (m *mmapper) Munmap(data []byte) (err error) {
73	if len(data) == 0 || len(data) != cap(data) {
74		return EINVAL
75	}
76
77	// Find the base of the mapping.
78	p := &data[cap(data)-1]
79	m.Lock()
80	defer m.Unlock()
81	b := m.active[p]
82	if b == nil || &b[0] != &data[0] {
83		return EINVAL
84	}
85
86	// Unmap the memory and update m.
87	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
88		return errno
89	}
90	delete(m.active, p)
91	return nil
92}
93
94// An Errno is an unsigned number describing an error condition.
95// It implements the error interface. The zero Errno is by convention
96// a non-error, so code to convert from Errno to error should use:
97//
98//	err = nil
99//	if errno != 0 {
100//		err = errno
101//	}
102//
103// Errno values can be tested against error values using [errors.Is].
104// For example:
105//
106//	_, _, err := syscall.Syscall(...)
107//	if errors.Is(err, fs.ErrNotExist) ...
108type Errno uintptr
109
110func (e Errno) Error() string {
111	if 0 <= int(e) && int(e) < len(errors) {
112		s := errors[e]
113		if s != "" {
114			return s
115		}
116	}
117	return "errno " + itoa.Itoa(int(e))
118}
119
120func (e Errno) Is(target error) bool {
121	switch target {
122	case oserror.ErrPermission:
123		return e == EACCES || e == EPERM
124	case oserror.ErrExist:
125		return e == EEXIST || e == ENOTEMPTY
126	case oserror.ErrNotExist:
127		return e == ENOENT
128	case errorspkg.ErrUnsupported:
129		return e == ENOSYS || e == ENOTSUP || e == EOPNOTSUPP
130	}
131	return false
132}
133
134func (e Errno) Temporary() bool {
135	return e == EINTR || e == EMFILE || e == ENFILE || e.Timeout()
136}
137
138func (e Errno) Timeout() bool {
139	return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
140}
141
142// Do the interface allocations only once for common
143// Errno values.
144var (
145	errEAGAIN error = EAGAIN
146	errEINVAL error = EINVAL
147	errENOENT error = ENOENT
148)
149
150// errnoErr returns common boxed Errno values, to prevent
151// allocations at runtime.
152func errnoErr(e Errno) error {
153	switch e {
154	case 0:
155		return nil
156	case EAGAIN:
157		return errEAGAIN
158	case EINVAL:
159		return errEINVAL
160	case ENOENT:
161		return errENOENT
162	}
163	return e
164}
165
166// A Signal is a number describing a process signal.
167// It implements the [os.Signal] interface.
168type Signal int
169
170func (s Signal) Signal() {}
171
172func (s Signal) String() string {
173	if 0 <= s && int(s) < len(signals) {
174		str := signals[s]
175		if str != "" {
176			return str
177		}
178	}
179	return "signal " + itoa.Itoa(int(s))
180}
181
182func Read(fd int, p []byte) (n int, err error) {
183	n, err = read(fd, p)
184	if race.Enabled {
185		if n > 0 {
186			race.WriteRange(unsafe.Pointer(&p[0]), n)
187		}
188		if err == nil {
189			race.Acquire(unsafe.Pointer(&ioSync))
190		}
191	}
192	if msan.Enabled && n > 0 {
193		msan.Write(unsafe.Pointer(&p[0]), uintptr(n))
194	}
195	if asan.Enabled && n > 0 {
196		asan.Write(unsafe.Pointer(&p[0]), uintptr(n))
197	}
198	return
199}
200
201func Write(fd int, p []byte) (n int, err error) {
202	if race.Enabled {
203		race.ReleaseMerge(unsafe.Pointer(&ioSync))
204	}
205	if faketime && (fd == 1 || fd == 2) {
206		n = faketimeWrite(fd, p)
207		if n < 0 {
208			n, err = 0, errnoErr(Errno(-n))
209		}
210	} else {
211		n, err = write(fd, p)
212	}
213	if race.Enabled && n > 0 {
214		race.ReadRange(unsafe.Pointer(&p[0]), n)
215	}
216	if msan.Enabled && n > 0 {
217		msan.Read(unsafe.Pointer(&p[0]), uintptr(n))
218	}
219	if asan.Enabled && n > 0 {
220		asan.Read(unsafe.Pointer(&p[0]), uintptr(n))
221	}
222	return
223}
224
225func Pread(fd int, p []byte, offset int64) (n int, err error) {
226	n, err = pread(fd, p, offset)
227	if race.Enabled {
228		if n > 0 {
229			race.WriteRange(unsafe.Pointer(&p[0]), n)
230		}
231		if err == nil {
232			race.Acquire(unsafe.Pointer(&ioSync))
233		}
234	}
235	if msan.Enabled && n > 0 {
236		msan.Write(unsafe.Pointer(&p[0]), uintptr(n))
237	}
238	if asan.Enabled && n > 0 {
239		asan.Write(unsafe.Pointer(&p[0]), uintptr(n))
240	}
241	return
242}
243
244func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
245	if race.Enabled {
246		race.ReleaseMerge(unsafe.Pointer(&ioSync))
247	}
248	n, err = pwrite(fd, p, offset)
249	if race.Enabled && n > 0 {
250		race.ReadRange(unsafe.Pointer(&p[0]), n)
251	}
252	if msan.Enabled && n > 0 {
253		msan.Read(unsafe.Pointer(&p[0]), uintptr(n))
254	}
255	if asan.Enabled && n > 0 {
256		asan.Read(unsafe.Pointer(&p[0]), uintptr(n))
257	}
258	return
259}
260
261// For testing: clients can set this flag to force
262// creation of IPv6 sockets to return [EAFNOSUPPORT].
263var SocketDisableIPv6 bool
264
265type Sockaddr interface {
266	sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs
267}
268
269type SockaddrInet4 struct {
270	Port int
271	Addr [4]byte
272	raw  RawSockaddrInet4
273}
274
275type SockaddrInet6 struct {
276	Port   int
277	ZoneId uint32
278	Addr   [16]byte
279	raw    RawSockaddrInet6
280}
281
282type SockaddrUnix struct {
283	Name string
284	raw  RawSockaddrUnix
285}
286
287func Bind(fd int, sa Sockaddr) (err error) {
288	ptr, n, err := sa.sockaddr()
289	if err != nil {
290		return err
291	}
292	return bind(fd, ptr, n)
293}
294
295func Connect(fd int, sa Sockaddr) (err error) {
296	ptr, n, err := sa.sockaddr()
297	if err != nil {
298		return err
299	}
300	return connect(fd, ptr, n)
301}
302
303func Getpeername(fd int) (sa Sockaddr, err error) {
304	var rsa RawSockaddrAny
305	var len _Socklen = SizeofSockaddrAny
306	if err = getpeername(fd, &rsa, &len); err != nil {
307		return
308	}
309	return anyToSockaddr(&rsa)
310}
311
312func GetsockoptInt(fd, level, opt int) (value int, err error) {
313	var n int32
314	vallen := _Socklen(4)
315	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
316	return int(n), err
317}
318
319func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
320	var rsa RawSockaddrAny
321	var len _Socklen = SizeofSockaddrAny
322	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
323		return
324	}
325	if rsa.Addr.Family != AF_UNSPEC {
326		from, err = anyToSockaddr(&rsa)
327	}
328	return
329}
330
331func recvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) {
332	var rsa RawSockaddrAny
333	var socklen _Socklen = SizeofSockaddrAny
334	if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil {
335		return
336	}
337	pp := (*RawSockaddrInet4)(unsafe.Pointer(&rsa))
338	port := (*[2]byte)(unsafe.Pointer(&pp.Port))
339	from.Port = int(port[0])<<8 + int(port[1])
340	from.Addr = pp.Addr
341	return
342}
343
344func recvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) {
345	var rsa RawSockaddrAny
346	var socklen _Socklen = SizeofSockaddrAny
347	if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil {
348		return
349	}
350	pp := (*RawSockaddrInet6)(unsafe.Pointer(&rsa))
351	port := (*[2]byte)(unsafe.Pointer(&pp.Port))
352	from.Port = int(port[0])<<8 + int(port[1])
353	from.ZoneId = pp.Scope_id
354	from.Addr = pp.Addr
355	return
356}
357
358func recvmsgInet4(fd int, p, oob []byte, flags int, from *SockaddrInet4) (n, oobn int, recvflags int, err error) {
359	var rsa RawSockaddrAny
360	n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa)
361	if err != nil {
362		return
363	}
364	pp := (*RawSockaddrInet4)(unsafe.Pointer(&rsa))
365	port := (*[2]byte)(unsafe.Pointer(&pp.Port))
366	from.Port = int(port[0])<<8 + int(port[1])
367	from.Addr = pp.Addr
368	return
369}
370
371func recvmsgInet6(fd int, p, oob []byte, flags int, from *SockaddrInet6) (n, oobn int, recvflags int, err error) {
372	var rsa RawSockaddrAny
373	n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa)
374	if err != nil {
375		return
376	}
377	pp := (*RawSockaddrInet6)(unsafe.Pointer(&rsa))
378	port := (*[2]byte)(unsafe.Pointer(&pp.Port))
379	from.Port = int(port[0])<<8 + int(port[1])
380	from.ZoneId = pp.Scope_id
381	from.Addr = pp.Addr
382	return
383}
384
385func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
386	var rsa RawSockaddrAny
387	n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa)
388	// source address is only specified if the socket is unconnected
389	if rsa.Addr.Family != AF_UNSPEC {
390		from, err = anyToSockaddr(&rsa)
391	}
392	return
393}
394
395func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
396	_, err = SendmsgN(fd, p, oob, to, flags)
397	return
398}
399
400func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
401	var ptr unsafe.Pointer
402	var salen _Socklen
403	if to != nil {
404		ptr, salen, err = to.sockaddr()
405		if err != nil {
406			return 0, err
407		}
408	}
409	return sendmsgN(fd, p, oob, ptr, salen, flags)
410}
411
412func sendmsgNInet4(fd int, p, oob []byte, to *SockaddrInet4, flags int) (n int, err error) {
413	ptr, salen, err := to.sockaddr()
414	if err != nil {
415		return 0, err
416	}
417	return sendmsgN(fd, p, oob, ptr, salen, flags)
418}
419
420func sendmsgNInet6(fd int, p, oob []byte, to *SockaddrInet6, flags int) (n int, err error) {
421	ptr, salen, err := to.sockaddr()
422	if err != nil {
423		return 0, err
424	}
425	return sendmsgN(fd, p, oob, ptr, salen, flags)
426}
427
428func sendtoInet4(fd int, p []byte, flags int, to *SockaddrInet4) (err error) {
429	ptr, n, err := to.sockaddr()
430	if err != nil {
431		return err
432	}
433	return sendto(fd, p, flags, ptr, n)
434}
435
436func sendtoInet6(fd int, p []byte, flags int, to *SockaddrInet6) (err error) {
437	ptr, n, err := to.sockaddr()
438	if err != nil {
439		return err
440	}
441	return sendto(fd, p, flags, ptr, n)
442}
443
444func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
445	var (
446		ptr   unsafe.Pointer
447		salen _Socklen
448	)
449	if to != nil {
450		ptr, salen, err = to.sockaddr()
451		if err != nil {
452			return err
453		}
454	}
455	return sendto(fd, p, flags, ptr, salen)
456}
457
458func SetsockoptByte(fd, level, opt int, value byte) (err error) {
459	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
460}
461
462func SetsockoptInt(fd, level, opt int, value int) (err error) {
463	var n = int32(value)
464	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
465}
466
467func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
468	return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
469}
470
471func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
472	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq)
473}
474
475func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
476	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq)
477}
478
479func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
480	return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
481}
482
483func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
484	return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger)
485}
486
487func SetsockoptString(fd, level, opt int, s string) (err error) {
488	var p unsafe.Pointer
489	if len(s) > 0 {
490		p = unsafe.Pointer(&[]byte(s)[0])
491	}
492	return setsockopt(fd, level, opt, p, uintptr(len(s)))
493}
494
495func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
496	return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv))
497}
498
499func Socket(domain, typ, proto int) (fd int, err error) {
500	if domain == AF_INET6 && SocketDisableIPv6 {
501		return -1, EAFNOSUPPORT
502	}
503	fd, err = socket(domain, typ, proto)
504	return
505}
506
507func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
508	var fdx [2]int32
509	err = socketpair(domain, typ, proto, &fdx)
510	if err == nil {
511		fd[0] = int(fdx[0])
512		fd[1] = int(fdx[1])
513	}
514	return
515}
516
517func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
518	if race.Enabled {
519		race.ReleaseMerge(unsafe.Pointer(&ioSync))
520	}
521	return sendfile(outfd, infd, offset, count)
522}
523
524var ioSync int64
525