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
5// +build s390x,linux
6
7package unix
8
9import (
10	"unsafe"
11)
12
13//sys	Dup2(oldfd int, newfd int) (err error)
14//sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
15//sys	Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
16//sys	Fchown(fd int, uid int, gid int) (err error)
17//sys	Fstat(fd int, stat *Stat_t) (err error)
18//sys	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT
19//sys	Fstatfs(fd int, buf *Statfs_t) (err error)
20//sys	Ftruncate(fd int, length int64) (err error)
21//sysnb	Getegid() (egid int)
22//sysnb	Geteuid() (euid int)
23//sysnb	Getgid() (gid int)
24//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error)
25//sysnb	Getuid() (uid int)
26//sysnb	InotifyInit() (fd int, err error)
27//sys	Lchown(path string, uid int, gid int) (err error)
28//sys	Lstat(path string, stat *Stat_t) (err error)
29//sys	Pause() (err error)
30//sys	Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
31//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
32//sys	Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
33//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
34//sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
35//sys	Setfsgid(gid int) (err error)
36//sys	Setfsuid(uid int) (err error)
37//sysnb	Setregid(rgid int, egid int) (err error)
38//sysnb	Setresgid(rgid int, egid int, sgid int) (err error)
39//sysnb	Setresuid(ruid int, euid int, suid int) (err error)
40//sysnb	Setrlimit(resource int, rlim *Rlimit) (err error)
41//sysnb	Setreuid(ruid int, euid int) (err error)
42//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
43//sys	Stat(path string, stat *Stat_t) (err error)
44//sys	Statfs(path string, buf *Statfs_t) (err error)
45//sys	SyncFileRange(fd int, off int64, n int64, flags int) (err error)
46//sys	Truncate(path string, length int64) (err error)
47//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
48//sysnb	setgroups(n int, list *_Gid_t) (err error)
49
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
66func setTimespec(sec, nsec int64) Timespec {
67	return Timespec{Sec: sec, Nsec: nsec}
68}
69
70func setTimeval(sec, usec int64) Timeval {
71	return Timeval{Sec: sec, Usec: usec}
72}
73
74//sysnb pipe2(p *[2]_C_int, flags int) (err error)
75
76func Pipe(p []int) (err error) {
77	if len(p) != 2 {
78		return EINVAL
79	}
80	var pp [2]_C_int
81	err = pipe2(&pp, 0) // pipe2 is the same as pipe when flags are set to 0.
82	p[0] = int(pp[0])
83	p[1] = int(pp[1])
84	return
85}
86
87func Pipe2(p []int, flags int) (err error) {
88	if len(p) != 2 {
89		return EINVAL
90	}
91	var pp [2]_C_int
92	err = pipe2(&pp, flags)
93	p[0] = int(pp[0])
94	p[1] = int(pp[1])
95	return
96}
97
98func Ioperm(from int, num int, on int) (err error) {
99	return ENOSYS
100}
101
102func Iopl(level int) (err error) {
103	return ENOSYS
104}
105
106func (r *PtraceRegs) PC() uint64 { return r.Psw.Addr }
107
108func (r *PtraceRegs) SetPC(pc uint64) { r.Psw.Addr = pc }
109
110func (iov *Iovec) SetLen(length int) {
111	iov.Len = uint64(length)
112}
113
114func (msghdr *Msghdr) SetControllen(length int) {
115	msghdr.Controllen = uint64(length)
116}
117
118func (cmsg *Cmsghdr) SetLen(length int) {
119	cmsg.Len = uint64(length)
120}
121
122// Linux on s390x uses the old mmap interface, which requires arguments to be passed in a struct.
123// mmap2 also requires arguments to be passed in a struct; it is currently not exposed in <asm/unistd.h>.
124func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
125	mmap_args := [6]uintptr{addr, length, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset)}
126	r0, _, e1 := Syscall(SYS_MMAP, uintptr(unsafe.Pointer(&mmap_args[0])), 0, 0)
127	xaddr = uintptr(r0)
128	if e1 != 0 {
129		err = errnoErr(e1)
130	}
131	return
132}
133
134// On s390x Linux, all the socket calls go through an extra indirection.
135// The arguments to the underlying system call (SYS_SOCKETCALL) are the
136// number below and a pointer to an array of uintptr.
137const (
138	// see linux/net.h
139	netSocket      = 1
140	netBind        = 2
141	netConnect     = 3
142	netListen      = 4
143	netAccept      = 5
144	netGetSockName = 6
145	netGetPeerName = 7
146	netSocketPair  = 8
147	netSend        = 9
148	netRecv        = 10
149	netSendTo      = 11
150	netRecvFrom    = 12
151	netShutdown    = 13
152	netSetSockOpt  = 14
153	netGetSockOpt  = 15
154	netSendMsg     = 16
155	netRecvMsg     = 17
156	netAccept4     = 18
157	netRecvMMsg    = 19
158	netSendMMsg    = 20
159)
160
161func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (int, error) {
162	args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))}
163	fd, _, err := Syscall(SYS_SOCKETCALL, netAccept, uintptr(unsafe.Pointer(&args)), 0)
164	if err != 0 {
165		return 0, err
166	}
167	return int(fd), nil
168}
169
170func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (int, error) {
171	args := [4]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags)}
172	fd, _, err := Syscall(SYS_SOCKETCALL, netAccept4, uintptr(unsafe.Pointer(&args)), 0)
173	if err != 0 {
174		return 0, err
175	}
176	return int(fd), nil
177}
178
179func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) error {
180	args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))}
181	_, _, err := RawSyscall(SYS_SOCKETCALL, netGetSockName, uintptr(unsafe.Pointer(&args)), 0)
182	if err != 0 {
183		return err
184	}
185	return nil
186}
187
188func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) error {
189	args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))}
190	_, _, err := RawSyscall(SYS_SOCKETCALL, netGetPeerName, uintptr(unsafe.Pointer(&args)), 0)
191	if err != 0 {
192		return err
193	}
194	return nil
195}
196
197func socketpair(domain int, typ int, flags int, fd *[2]int32) error {
198	args := [4]uintptr{uintptr(domain), uintptr(typ), uintptr(flags), uintptr(unsafe.Pointer(fd))}
199	_, _, err := RawSyscall(SYS_SOCKETCALL, netSocketPair, uintptr(unsafe.Pointer(&args)), 0)
200	if err != 0 {
201		return err
202	}
203	return nil
204}
205
206func bind(s int, addr unsafe.Pointer, addrlen _Socklen) error {
207	args := [3]uintptr{uintptr(s), uintptr(addr), uintptr(addrlen)}
208	_, _, err := Syscall(SYS_SOCKETCALL, netBind, uintptr(unsafe.Pointer(&args)), 0)
209	if err != 0 {
210		return err
211	}
212	return nil
213}
214
215func connect(s int, addr unsafe.Pointer, addrlen _Socklen) error {
216	args := [3]uintptr{uintptr(s), uintptr(addr), uintptr(addrlen)}
217	_, _, err := Syscall(SYS_SOCKETCALL, netConnect, uintptr(unsafe.Pointer(&args)), 0)
218	if err != 0 {
219		return err
220	}
221	return nil
222}
223
224func socket(domain int, typ int, proto int) (int, error) {
225	args := [3]uintptr{uintptr(domain), uintptr(typ), uintptr(proto)}
226	fd, _, err := RawSyscall(SYS_SOCKETCALL, netSocket, uintptr(unsafe.Pointer(&args)), 0)
227	if err != 0 {
228		return 0, err
229	}
230	return int(fd), nil
231}
232
233func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) error {
234	args := [5]uintptr{uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen))}
235	_, _, err := Syscall(SYS_SOCKETCALL, netGetSockOpt, uintptr(unsafe.Pointer(&args)), 0)
236	if err != 0 {
237		return err
238	}
239	return nil
240}
241
242func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) error {
243	args := [4]uintptr{uintptr(s), uintptr(level), uintptr(name), uintptr(val)}
244	_, _, err := Syscall(SYS_SOCKETCALL, netSetSockOpt, uintptr(unsafe.Pointer(&args)), 0)
245	if err != 0 {
246		return err
247	}
248	return nil
249}
250
251func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (int, error) {
252	var base uintptr
253	if len(p) > 0 {
254		base = uintptr(unsafe.Pointer(&p[0]))
255	}
256	args := [6]uintptr{uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))}
257	n, _, err := Syscall(SYS_SOCKETCALL, netRecvFrom, uintptr(unsafe.Pointer(&args)), 0)
258	if err != 0 {
259		return 0, err
260	}
261	return int(n), nil
262}
263
264func sendto(s int, p []byte, flags int, to unsafe.Pointer, addrlen _Socklen) error {
265	var base uintptr
266	if len(p) > 0 {
267		base = uintptr(unsafe.Pointer(&p[0]))
268	}
269	args := [6]uintptr{uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(to), uintptr(addrlen)}
270	_, _, err := Syscall(SYS_SOCKETCALL, netSendTo, uintptr(unsafe.Pointer(&args)), 0)
271	if err != 0 {
272		return err
273	}
274	return nil
275}
276
277func recvmsg(s int, msg *Msghdr, flags int) (int, error) {
278	args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)}
279	n, _, err := Syscall(SYS_SOCKETCALL, netRecvMsg, uintptr(unsafe.Pointer(&args)), 0)
280	if err != 0 {
281		return 0, err
282	}
283	return int(n), nil
284}
285
286func sendmsg(s int, msg *Msghdr, flags int) (int, error) {
287	args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)}
288	n, _, err := Syscall(SYS_SOCKETCALL, netSendMsg, uintptr(unsafe.Pointer(&args)), 0)
289	if err != 0 {
290		return 0, err
291	}
292	return int(n), nil
293}
294
295func Listen(s int, n int) error {
296	args := [2]uintptr{uintptr(s), uintptr(n)}
297	_, _, err := Syscall(SYS_SOCKETCALL, netListen, uintptr(unsafe.Pointer(&args)), 0)
298	if err != 0 {
299		return err
300	}
301	return nil
302}
303
304func Shutdown(s, how int) error {
305	args := [2]uintptr{uintptr(s), uintptr(how)}
306	_, _, err := Syscall(SYS_SOCKETCALL, netShutdown, uintptr(unsafe.Pointer(&args)), 0)
307	if err != 0 {
308		return err
309	}
310	return nil
311}
312
313//sys	poll(fds *PollFd, nfds int, timeout int) (n int, err error)
314
315func Poll(fds []PollFd, timeout int) (n int, err error) {
316	if len(fds) == 0 {
317		return poll(nil, 0, timeout)
318	}
319	return poll(&fds[0], len(fds), timeout)
320}
321