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 aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
6// +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
7
8package syscall
9
10import (
11	"internal/race"
12	"internal/unsafeheader"
13	"runtime"
14	"sync"
15	"unsafe"
16)
17
18var (
19	Stdin  = 0
20	Stdout = 1
21	Stderr = 2
22)
23
24const (
25	darwin64Bit = (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && sizeofPtr == 8
26	netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4
27)
28
29// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
30func clen(n []byte) int {
31	for i := 0; i < len(n); i++ {
32		if n[i] == 0 {
33			return i
34		}
35	}
36	return len(n)
37}
38
39// Mmap manager, for use by operating system-specific implementations.
40// Gccgo only has one implementation but we do this to correspond to gc.
41
42type mmapper struct {
43	sync.Mutex
44	active map[*byte][]byte // active mappings; key is last byte in mapping
45	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
46	munmap func(addr uintptr, length uintptr) error
47}
48
49func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
50	if length <= 0 {
51		return nil, EINVAL
52	}
53
54	// Map the requested memory.
55	addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
56	if errno != nil {
57		return nil, errno
58	}
59
60	// Use unsafe to turn addr into a []byte.
61	var b []byte
62	hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b))
63	hdr.Data = unsafe.Pointer(addr)
64	hdr.Cap = length
65	hdr.Len = length
66
67	// Register mapping in m and return it.
68	p := &b[cap(b)-1]
69	m.Lock()
70	defer m.Unlock()
71	m.active[p] = b
72	return b, nil
73}
74
75func (m *mmapper) Munmap(data []byte) (err error) {
76	if len(data) == 0 || len(data) != cap(data) {
77		return EINVAL
78	}
79
80	// Find the base of the mapping.
81	p := &data[cap(data)-1]
82	m.Lock()
83	defer m.Unlock()
84	b := m.active[p]
85	if b == nil || &b[0] != &data[0] {
86		return EINVAL
87	}
88
89	// Unmap the memory and update m.
90	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
91		return errno
92	}
93	delete(m.active, p)
94	return nil
95}
96
97var mapper = &mmapper{
98	active: make(map[*byte][]byte),
99	mmap:   mmap,
100	munmap: munmap,
101}
102
103func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
104	return mapper.Mmap(fd, offset, length, prot, flags)
105}
106
107func Munmap(b []byte) (err error) {
108	return mapper.Munmap(b)
109}
110
111// Do the interface allocations only once for common
112// Errno values.
113var (
114	errEAGAIN error = EAGAIN
115	errEINVAL error = EINVAL
116	errENOENT error = ENOENT
117)
118
119// errnoErr returns common boxed Errno values, to prevent
120// allocations at runtime.
121func errnoErr(e Errno) error {
122	switch e {
123	case 0:
124		return nil
125	case EAGAIN:
126		return errEAGAIN
127	case EINVAL:
128		return errEINVAL
129	case ENOENT:
130		return errENOENT
131	}
132	return e
133}
134
135// A Signal is a number describing a process signal.
136// It implements the os.Signal interface.
137type Signal int
138
139func (s Signal) Signal() {}
140
141func Signame(s Signal) string
142
143func (s Signal) String() string {
144	return Signame(s)
145}
146
147func Read(fd int, p []byte) (n int, err error) {
148	n, err = read(fd, p)
149	if race.Enabled {
150		if n > 0 {
151			race.WriteRange(unsafe.Pointer(&p[0]), n)
152		}
153		if err == nil {
154			race.Acquire(unsafe.Pointer(&ioSync))
155		}
156	}
157	if msanenabled && n > 0 {
158		msanWrite(unsafe.Pointer(&p[0]), n)
159	}
160	return
161}
162
163func Write(fd int, p []byte) (n int, err error) {
164	if race.Enabled {
165		race.ReleaseMerge(unsafe.Pointer(&ioSync))
166	}
167	if faketime && (fd == 1 || fd == 2) {
168		n = faketimeWrite(fd, p)
169		if n < 0 {
170			n, err = 0, errnoErr(Errno(-n))
171		}
172	} else {
173		n, err = write(fd, p)
174	}
175	if race.Enabled && n > 0 {
176		race.ReadRange(unsafe.Pointer(&p[0]), n)
177	}
178	if msanenabled && n > 0 {
179		msanRead(unsafe.Pointer(&p[0]), n)
180	}
181	return
182}
183
184var ioSync int64
185