1// Copyright 2016 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
5package syscall
6
7import "unsafe"
8
9const (
10	_SYS_setgroups  = SYS_SETGROUPS
11	_SYS_clone3     = 435
12	_SYS_faccessat2 = 439
13	_SYS_fchmodat2  = 452
14)
15
16//sys	Dup2(oldfd int, newfd int) (err error)
17//sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
18//sys	Fchown(fd int, uid int, gid int) (err error)
19//sys	Fstat(fd int, stat *Stat_t) (err error)
20//sys	fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT
21//sys	Fstatfs(fd int, buf *Statfs_t) (err error)
22//sys	Ftruncate(fd int, length int64) (err error)
23//sysnb	Getegid() (egid int)
24//sysnb	Geteuid() (euid int)
25//sysnb	Getgid() (gid int)
26//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_GETRLIMIT
27//sysnb	Getuid() (uid int)
28//sysnb	InotifyInit() (fd int, err error)
29//sys	Lchown(path string, uid int, gid int) (err error)
30//sys	Lstat(path string, stat *Stat_t) (err error)
31//sys	Pause() (err error)
32//sys	pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
33//sys	pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
34//sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
35//sys	Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
36//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
37//sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
38//sys	Setfsgid(gid int) (err error)
39//sys	Setfsuid(uid int) (err error)
40//sysnb	setrlimit(resource int, rlim *Rlimit) (err error) = SYS_SETRLIMIT
41//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
42//sys	Stat(path string, stat *Stat_t) (err error)
43//sys	Statfs(path string, buf *Statfs_t) (err error)
44//sys	SyncFileRange(fd int, off int64, n int64, flags int) (err error) = SYS_SYNC_FILE_RANGE
45//sys	Truncate(path string, length int64) (err error)
46//sys	Ustat(dev int, ubuf *Ustat_t) (err error)
47//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
48
49//sys	futimesat(dirfd int, path string, times *[2]Timeval) (err error)
50//sysnb	Gettimeofday(tv *Timeval) (err error)
51
52func Time(t *Time_t) (tt Time_t, err error) {
53	var tv Timeval
54	err = Gettimeofday(&tv)
55	if err != nil {
56		return 0, err
57	}
58	if t != nil {
59		*t = Time_t(tv.Sec)
60	}
61	return Time_t(tv.Sec), nil
62}
63
64//sys	Utime(path string, buf *Utimbuf) (err error)
65//sys	utimes(path string, times *[2]Timeval) (err error)
66
67func setTimespec(sec, nsec int64) Timespec {
68	return Timespec{Sec: sec, Nsec: nsec}
69}
70
71func setTimeval(sec, usec int64) Timeval {
72	return Timeval{Sec: sec, Usec: usec}
73}
74
75// Linux on s390x uses the old mmap interface, which requires arguments to be passed in a struct.
76// mmap2 also requires arguments to be passed in a struct; it is currently not exposed in <asm/unistd.h>.
77func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
78	mmap_args := [6]uintptr{addr, length, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset)}
79	r0, _, e1 := Syscall(SYS_MMAP, uintptr(unsafe.Pointer(&mmap_args[0])), 0, 0)
80	xaddr = uintptr(r0)
81	if e1 != 0 {
82		err = errnoErr(e1)
83	}
84	return
85}
86
87// On s390x Linux, all the socket calls go through an extra indirection.
88// The arguments to the underlying system call are the number below
89// and a pointer to an array of uintptr.  We hide the pointer in the
90// socketcall assembly to avoid allocation on every system call.
91
92const (
93	// see linux/net.h
94	_SOCKET      = 1
95	_BIND        = 2
96	_CONNECT     = 3
97	_LISTEN      = 4
98	_ACCEPT      = 5
99	_GETSOCKNAME = 6
100	_GETPEERNAME = 7
101	_SOCKETPAIR  = 8
102	_SEND        = 9
103	_RECV        = 10
104	_SENDTO      = 11
105	_RECVFROM    = 12
106	_SHUTDOWN    = 13
107	_SETSOCKOPT  = 14
108	_GETSOCKOPT  = 15
109	_SENDMSG     = 16
110	_RECVMSG     = 17
111	_ACCEPT4     = 18
112	_RECVMMSG    = 19
113	_SENDMMSG    = 20
114)
115
116func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err Errno)
117func rawsocketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err Errno)
118
119func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) {
120	fd, e := socketcall(_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0)
121	if e != 0 {
122		err = e
123	}
124	return
125}
126
127func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
128	_, e := rawsocketcall(_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
129	if e != 0 {
130		err = e
131	}
132	return
133}
134
135func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
136	_, e := rawsocketcall(_GETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
137	if e != 0 {
138		err = e
139	}
140	return
141}
142
143func socketpair(domain int, typ int, flags int, fd *[2]int32) (err error) {
144	_, e := rawsocketcall(_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(flags), uintptr(unsafe.Pointer(fd)), 0, 0)
145	if e != 0 {
146		err = e
147	}
148	return
149}
150
151func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
152	_, e := socketcall(_BIND, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
153	if e != 0 {
154		err = e
155	}
156	return
157}
158
159func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
160	_, e := socketcall(_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
161	if e != 0 {
162		err = e
163	}
164	return
165}
166
167func socket(domain int, typ int, proto int) (fd int, err error) {
168	fd, e := rawsocketcall(_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0)
169	if e != 0 {
170		err = e
171	}
172	return
173}
174
175func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) {
176	_, e := socketcall(_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
177	if e != 0 {
178		err = e
179	}
180	return
181}
182
183func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) {
184	_, e := socketcall(_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), vallen, 0)
185	if e != 0 {
186		err = e
187	}
188	return
189}
190
191func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
192	var base uintptr
193	if len(p) > 0 {
194		base = uintptr(unsafe.Pointer(&p[0]))
195	}
196	n, e := socketcall(_RECVFROM, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
197	if e != 0 {
198		err = e
199	}
200	return
201}
202
203func sendto(s int, p []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) {
204	var base uintptr
205	if len(p) > 0 {
206		base = uintptr(unsafe.Pointer(&p[0]))
207	}
208	_, e := socketcall(_SENDTO, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(to), uintptr(addrlen))
209	if e != 0 {
210		err = e
211	}
212	return
213}
214
215func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
216	n, e := socketcall(_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
217	if e != 0 {
218		err = e
219	}
220	return
221}
222
223func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
224	n, e := socketcall(_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
225	if e != 0 {
226		err = e
227	}
228	return
229}
230
231func Listen(s int, n int) (err error) {
232	_, e := socketcall(_LISTEN, uintptr(s), uintptr(n), 0, 0, 0, 0)
233	if e != 0 {
234		err = e
235	}
236	return
237}
238
239func Shutdown(s, how int) (err error) {
240	_, e := socketcall(_SHUTDOWN, uintptr(s), uintptr(how), 0, 0, 0, 0)
241	if e != 0 {
242		err = e
243	}
244	return
245}
246
247//go:nosplit
248func rawSetrlimit(resource int, rlim *Rlimit) Errno {
249	_, _, errno := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
250	return errno
251}
252
253func (r *PtraceRegs) PC() uint64 { return r.Psw.Addr }
254
255func (r *PtraceRegs) SetPC(pc uint64) { r.Psw.Addr = pc }
256
257func (iov *Iovec) SetLen(length int) {
258	iov.Len = uint64(length)
259}
260
261func (msghdr *Msghdr) SetControllen(length int) {
262	msghdr.Controllen = uint64(length)
263}
264
265func (cmsg *Cmsghdr) SetLen(length int) {
266	cmsg.Len = uint64(length)
267}
268