1// Copyright 2020 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 zos && s390x
6// +build zos,s390x
7
8package unix
9
10import (
11	"bytes"
12	"runtime"
13	"sort"
14	"sync"
15	"syscall"
16	"unsafe"
17)
18
19const (
20	O_CLOEXEC = 0       // Dummy value (not supported).
21	AF_LOCAL  = AF_UNIX // AF_LOCAL is an alias for AF_UNIX
22)
23
24func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
25func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
26func syscall_syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
27func syscall_rawsyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
28func syscall_syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
29func syscall_rawsyscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
30
31func copyStat(stat *Stat_t, statLE *Stat_LE_t) {
32	stat.Dev = uint64(statLE.Dev)
33	stat.Ino = uint64(statLE.Ino)
34	stat.Nlink = uint64(statLE.Nlink)
35	stat.Mode = uint32(statLE.Mode)
36	stat.Uid = uint32(statLE.Uid)
37	stat.Gid = uint32(statLE.Gid)
38	stat.Rdev = uint64(statLE.Rdev)
39	stat.Size = statLE.Size
40	stat.Atim.Sec = int64(statLE.Atim)
41	stat.Atim.Nsec = 0 //zos doesn't return nanoseconds
42	stat.Mtim.Sec = int64(statLE.Mtim)
43	stat.Mtim.Nsec = 0 //zos doesn't return nanoseconds
44	stat.Ctim.Sec = int64(statLE.Ctim)
45	stat.Ctim.Nsec = 0 //zos doesn't return nanoseconds
46	stat.Blksize = int64(statLE.Blksize)
47	stat.Blocks = statLE.Blocks
48}
49
50func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
51func svcLoad(name *byte) unsafe.Pointer
52func svcUnload(name *byte, fnptr unsafe.Pointer) int64
53
54func (d *Dirent) NameString() string {
55	if d == nil {
56		return ""
57	}
58	return string(d.Name[:d.Namlen])
59}
60
61func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
62	if sa.Port < 0 || sa.Port > 0xFFFF {
63		return nil, 0, EINVAL
64	}
65	sa.raw.Len = SizeofSockaddrInet4
66	sa.raw.Family = AF_INET
67	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
68	p[0] = byte(sa.Port >> 8)
69	p[1] = byte(sa.Port)
70	sa.raw.Addr = sa.Addr
71	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
72}
73
74func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
75	if sa.Port < 0 || sa.Port > 0xFFFF {
76		return nil, 0, EINVAL
77	}
78	sa.raw.Len = SizeofSockaddrInet6
79	sa.raw.Family = AF_INET6
80	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
81	p[0] = byte(sa.Port >> 8)
82	p[1] = byte(sa.Port)
83	sa.raw.Scope_id = sa.ZoneId
84	sa.raw.Addr = sa.Addr
85	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
86}
87
88func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
89	name := sa.Name
90	n := len(name)
91	if n >= len(sa.raw.Path) || n == 0 {
92		return nil, 0, EINVAL
93	}
94	sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
95	sa.raw.Family = AF_UNIX
96	for i := 0; i < n; i++ {
97		sa.raw.Path[i] = int8(name[i])
98	}
99	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
100}
101
102func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) {
103	// TODO(neeilan): Implement use of first param (fd)
104	switch rsa.Addr.Family {
105	case AF_UNIX:
106		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
107		sa := new(SockaddrUnix)
108		// For z/OS, only replace NUL with @ when the
109		// length is not zero.
110		if pp.Len != 0 && pp.Path[0] == 0 {
111			// "Abstract" Unix domain socket.
112			// Rewrite leading NUL as @ for textual display.
113			// (This is the standard convention.)
114			// Not friendly to overwrite in place,
115			// but the callers below don't care.
116			pp.Path[0] = '@'
117		}
118
119		// Assume path ends at NUL.
120		//
121		// For z/OS, the length of the name is a field
122		// in the structure. To be on the safe side, we
123		// will still scan the name for a NUL but only
124		// to the length provided in the structure.
125		//
126		// This is not technically the Linux semantics for
127		// abstract Unix domain sockets--they are supposed
128		// to be uninterpreted fixed-size binary blobs--but
129		// everyone uses this convention.
130		n := 0
131		for n < int(pp.Len) && pp.Path[n] != 0 {
132			n++
133		}
134		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
135		sa.Name = string(bytes)
136		return sa, nil
137
138	case AF_INET:
139		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
140		sa := new(SockaddrInet4)
141		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
142		sa.Port = int(p[0])<<8 + int(p[1])
143		sa.Addr = pp.Addr
144		return sa, nil
145
146	case AF_INET6:
147		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
148		sa := new(SockaddrInet6)
149		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
150		sa.Port = int(p[0])<<8 + int(p[1])
151		sa.ZoneId = pp.Scope_id
152		sa.Addr = pp.Addr
153		return sa, nil
154	}
155	return nil, EAFNOSUPPORT
156}
157
158func Accept(fd int) (nfd int, sa Sockaddr, err error) {
159	var rsa RawSockaddrAny
160	var len _Socklen = SizeofSockaddrAny
161	nfd, err = accept(fd, &rsa, &len)
162	if err != nil {
163		return
164	}
165	// TODO(neeilan): Remove 0 in call
166	sa, err = anyToSockaddr(0, &rsa)
167	if err != nil {
168		Close(nfd)
169		nfd = 0
170	}
171	return
172}
173
174func (iov *Iovec) SetLen(length int) {
175	iov.Len = uint64(length)
176}
177
178func (msghdr *Msghdr) SetControllen(length int) {
179	msghdr.Controllen = int32(length)
180}
181
182func (cmsg *Cmsghdr) SetLen(length int) {
183	cmsg.Len = int32(length)
184}
185
186//sys   fcntl(fd int, cmd int, arg int) (val int, err error)
187//sys	read(fd int, p []byte) (n int, err error)
188//sys   readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
189//sys	write(fd int, p []byte) (n int, err error)
190
191//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = SYS___ACCEPT_A
192//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___BIND_A
193//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___CONNECT_A
194//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
195//sysnb	setgroups(n int, list *_Gid_t) (err error)
196//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
197//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
198//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
199//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
200//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETPEERNAME_A
201//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETSOCKNAME_A
202//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = SYS___RECVFROM_A
203//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = SYS___SENDTO_A
204//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___RECVMSG_A
205//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___SENDMSG_A
206//sys   mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) = SYS_MMAP
207//sys   munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP
208//sys   ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL
209
210//sys   Access(path string, mode uint32) (err error) = SYS___ACCESS_A
211//sys   Chdir(path string) (err error) = SYS___CHDIR_A
212//sys	Chown(path string, uid int, gid int) (err error) = SYS___CHOWN_A
213//sys	Chmod(path string, mode uint32) (err error) = SYS___CHMOD_A
214//sys   Creat(path string, mode uint32) (fd int, err error) = SYS___CREAT_A
215//sys	Dup(oldfd int) (fd int, err error)
216//sys	Dup2(oldfd int, newfd int) (err error)
217//sys	Errno2() (er2 int) = SYS___ERRNO2
218//sys	Err2ad() (eadd *int) = SYS___ERR2AD
219//sys	Exit(code int)
220//sys	Fchdir(fd int) (err error)
221//sys	Fchmod(fd int, mode uint32) (err error)
222//sys	Fchown(fd int, uid int, gid int) (err error)
223//sys	FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) = SYS_FCNTL
224//sys	fstat(fd int, stat *Stat_LE_t) (err error)
225
226func Fstat(fd int, stat *Stat_t) (err error) {
227	var statLE Stat_LE_t
228	err = fstat(fd, &statLE)
229	copyStat(stat, &statLE)
230	return
231}
232
233//sys	Fstatvfs(fd int, stat *Statvfs_t) (err error) = SYS_FSTATVFS
234//sys	Fsync(fd int) (err error)
235//sys	Ftruncate(fd int, length int64) (err error)
236//sys   Getpagesize() (pgsize int) = SYS_GETPAGESIZE
237//sys   Mprotect(b []byte, prot int) (err error) = SYS_MPROTECT
238//sys   Msync(b []byte, flags int) (err error) = SYS_MSYNC
239//sys   Poll(fds []PollFd, timeout int) (n int, err error) = SYS_POLL
240//sys   Times(tms *Tms) (ticks uintptr, err error) = SYS_TIMES
241//sys   W_Getmntent(buff *byte, size int) (lastsys int, err error) = SYS_W_GETMNTENT
242//sys   W_Getmntent_A(buff *byte, size int) (lastsys int, err error) = SYS___W_GETMNTENT_A
243
244//sys   mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) = SYS___MOUNT_A
245//sys   unmount(filesystem string, mtm int) (err error) = SYS___UMOUNT_A
246//sys   Chroot(path string) (err error) = SYS___CHROOT_A
247//sys   Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) = SYS_SELECT
248//sysnb Uname(buf *Utsname) (err error) = SYS___UNAME_A
249
250func Ptsname(fd int) (name string, err error) {
251	r0, _, e1 := syscall_syscall(SYS___PTSNAME_A, uintptr(fd), 0, 0)
252	name = u2s(unsafe.Pointer(r0))
253	if e1 != 0 {
254		err = errnoErr(e1)
255	}
256	return
257}
258
259func u2s(cstr unsafe.Pointer) string {
260	str := (*[1024]uint8)(cstr)
261	i := 0
262	for str[i] != 0 {
263		i++
264	}
265	return string(str[:i])
266}
267
268func Close(fd int) (err error) {
269	_, _, e1 := syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0)
270	for i := 0; e1 == EAGAIN && i < 10; i++ {
271		_, _, _ = syscall_syscall(SYS_USLEEP, uintptr(10), 0, 0)
272		_, _, e1 = syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0)
273	}
274	if e1 != 0 {
275		err = errnoErr(e1)
276	}
277	return
278}
279
280var mapper = &mmapper{
281	active: make(map[*byte][]byte),
282	mmap:   mmap,
283	munmap: munmap,
284}
285
286// Dummy function: there are no semantics for Madvise on z/OS
287func Madvise(b []byte, advice int) (err error) {
288	return
289}
290
291func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
292	return mapper.Mmap(fd, offset, length, prot, flags)
293}
294
295func Munmap(b []byte) (err error) {
296	return mapper.Munmap(b)
297}
298
299//sys   Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A
300//sysnb	Getegid() (egid int)
301//sysnb	Geteuid() (uid int)
302//sysnb	Getgid() (gid int)
303//sysnb	Getpid() (pid int)
304//sysnb	Getpgid(pid int) (pgid int, err error) = SYS_GETPGID
305
306func Getpgrp() (pid int) {
307	pid, _ = Getpgid(0)
308	return
309}
310
311//sysnb	Getppid() (pid int)
312//sys	Getpriority(which int, who int) (prio int, err error)
313//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_GETRLIMIT
314
315//sysnb getrusage(who int, rusage *rusage_zos) (err error) = SYS_GETRUSAGE
316
317func Getrusage(who int, rusage *Rusage) (err error) {
318	var ruz rusage_zos
319	err = getrusage(who, &ruz)
320	//Only the first two fields of Rusage are set
321	rusage.Utime.Sec = ruz.Utime.Sec
322	rusage.Utime.Usec = int64(ruz.Utime.Usec)
323	rusage.Stime.Sec = ruz.Stime.Sec
324	rusage.Stime.Usec = int64(ruz.Stime.Usec)
325	return
326}
327
328//sysnb Getsid(pid int) (sid int, err error) = SYS_GETSID
329//sysnb	Getuid() (uid int)
330//sysnb	Kill(pid int, sig Signal) (err error)
331//sys	Lchown(path string, uid int, gid int) (err error) = SYS___LCHOWN_A
332//sys	Link(path string, link string) (err error) = SYS___LINK_A
333//sys	Listen(s int, n int) (err error)
334//sys	lstat(path string, stat *Stat_LE_t) (err error) = SYS___LSTAT_A
335
336func Lstat(path string, stat *Stat_t) (err error) {
337	var statLE Stat_LE_t
338	err = lstat(path, &statLE)
339	copyStat(stat, &statLE)
340	return
341}
342
343//sys	Mkdir(path string, mode uint32) (err error) = SYS___MKDIR_A
344//sys   Mkfifo(path string, mode uint32) (err error) = SYS___MKFIFO_A
345//sys	Mknod(path string, mode uint32, dev int) (err error) = SYS___MKNOD_A
346//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
347//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
348//sys	Readlink(path string, buf []byte) (n int, err error) = SYS___READLINK_A
349//sys	Rename(from string, to string) (err error) = SYS___RENAME_A
350//sys	Rmdir(path string) (err error) = SYS___RMDIR_A
351//sys   Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
352//sys	Setpriority(which int, who int, prio int) (err error)
353//sysnb	Setpgid(pid int, pgid int) (err error) = SYS_SETPGID
354//sysnb	Setrlimit(resource int, lim *Rlimit) (err error)
355//sysnb	Setregid(rgid int, egid int) (err error) = SYS_SETREGID
356//sysnb	Setreuid(ruid int, euid int) (err error) = SYS_SETREUID
357//sysnb	Setsid() (pid int, err error) = SYS_SETSID
358//sys	Setuid(uid int) (err error) = SYS_SETUID
359//sys	Setgid(uid int) (err error) = SYS_SETGID
360//sys	Shutdown(fd int, how int) (err error)
361//sys	stat(path string, statLE *Stat_LE_t) (err error) = SYS___STAT_A
362
363func Stat(path string, sta *Stat_t) (err error) {
364	var statLE Stat_LE_t
365	err = stat(path, &statLE)
366	copyStat(sta, &statLE)
367	return
368}
369
370//sys	Symlink(path string, link string) (err error) = SYS___SYMLINK_A
371//sys	Sync() = SYS_SYNC
372//sys	Truncate(path string, length int64) (err error) = SYS___TRUNCATE_A
373//sys	Tcgetattr(fildes int, termptr *Termios) (err error) = SYS_TCGETATTR
374//sys	Tcsetattr(fildes int, when int, termptr *Termios) (err error) = SYS_TCSETATTR
375//sys	Umask(mask int) (oldmask int)
376//sys	Unlink(path string) (err error) = SYS___UNLINK_A
377//sys	Utime(path string, utim *Utimbuf) (err error) = SYS___UTIME_A
378
379//sys	open(path string, mode int, perm uint32) (fd int, err error) = SYS___OPEN_A
380
381func Open(path string, mode int, perm uint32) (fd int, err error) {
382	return open(path, mode, perm)
383}
384
385func Mkfifoat(dirfd int, path string, mode uint32) (err error) {
386	wd, err := Getwd()
387	if err != nil {
388		return err
389	}
390
391	if err := Fchdir(dirfd); err != nil {
392		return err
393	}
394	defer Chdir(wd)
395
396	return Mkfifo(path, mode)
397}
398
399//sys	remove(path string) (err error)
400
401func Remove(path string) error {
402	return remove(path)
403}
404
405const ImplementsGetwd = true
406
407func Getcwd(buf []byte) (n int, err error) {
408	var p unsafe.Pointer
409	if len(buf) > 0 {
410		p = unsafe.Pointer(&buf[0])
411	} else {
412		p = unsafe.Pointer(&_zero)
413	}
414	_, _, e := syscall_syscall(SYS___GETCWD_A, uintptr(p), uintptr(len(buf)), 0)
415	n = clen(buf) + 1
416	if e != 0 {
417		err = errnoErr(e)
418	}
419	return
420}
421
422func Getwd() (wd string, err error) {
423	var buf [PathMax]byte
424	n, err := Getcwd(buf[0:])
425	if err != nil {
426		return "", err
427	}
428	// Getcwd returns the number of bytes written to buf, including the NUL.
429	if n < 1 || n > len(buf) || buf[n-1] != 0 {
430		return "", EINVAL
431	}
432	return string(buf[0 : n-1]), nil
433}
434
435func Getgroups() (gids []int, err error) {
436	n, err := getgroups(0, nil)
437	if err != nil {
438		return nil, err
439	}
440	if n == 0 {
441		return nil, nil
442	}
443
444	// Sanity check group count.  Max is 1<<16 on Linux.
445	if n < 0 || n > 1<<20 {
446		return nil, EINVAL
447	}
448
449	a := make([]_Gid_t, n)
450	n, err = getgroups(n, &a[0])
451	if err != nil {
452		return nil, err
453	}
454	gids = make([]int, n)
455	for i, v := range a[0:n] {
456		gids[i] = int(v)
457	}
458	return
459}
460
461func Setgroups(gids []int) (err error) {
462	if len(gids) == 0 {
463		return setgroups(0, nil)
464	}
465
466	a := make([]_Gid_t, len(gids))
467	for i, v := range gids {
468		a[i] = _Gid_t(v)
469	}
470	return setgroups(len(a), &a[0])
471}
472
473func gettid() uint64
474
475func Gettid() (tid int) {
476	return int(gettid())
477}
478
479type WaitStatus uint32
480
481// Wait status is 7 bits at bottom, either 0 (exited),
482// 0x7F (stopped), or a signal number that caused an exit.
483// The 0x80 bit is whether there was a core dump.
484// An extra number (exit code, signal causing a stop)
485// is in the high bits.  At least that's the idea.
486// There are various irregularities.  For example, the
487// "continued" status is 0xFFFF, distinguishing itself
488// from stopped via the core dump bit.
489
490const (
491	mask    = 0x7F
492	core    = 0x80
493	exited  = 0x00
494	stopped = 0x7F
495	shift   = 8
496)
497
498func (w WaitStatus) Exited() bool { return w&mask == exited }
499
500func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited }
501
502func (w WaitStatus) Stopped() bool { return w&0xFF == stopped }
503
504func (w WaitStatus) Continued() bool { return w == 0xFFFF }
505
506func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
507
508func (w WaitStatus) ExitStatus() int {
509	if !w.Exited() {
510		return -1
511	}
512	return int(w>>shift) & 0xFF
513}
514
515func (w WaitStatus) Signal() Signal {
516	if !w.Signaled() {
517		return -1
518	}
519	return Signal(w & mask)
520}
521
522func (w WaitStatus) StopSignal() Signal {
523	if !w.Stopped() {
524		return -1
525	}
526	return Signal(w>>shift) & 0xFF
527}
528
529func (w WaitStatus) TrapCause() int { return -1 }
530
531//sys	waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error)
532
533func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
534	// TODO(mundaym): z/OS doesn't have wait4. I don't think getrusage does what we want.
535	// At the moment rusage will not be touched.
536	var status _C_int
537	wpid, err = waitpid(pid, &status, options)
538	if wstatus != nil {
539		*wstatus = WaitStatus(status)
540	}
541	return
542}
543
544//sysnb	gettimeofday(tv *timeval_zos) (err error)
545
546func Gettimeofday(tv *Timeval) (err error) {
547	var tvz timeval_zos
548	err = gettimeofday(&tvz)
549	tv.Sec = tvz.Sec
550	tv.Usec = int64(tvz.Usec)
551	return
552}
553
554func Time(t *Time_t) (tt Time_t, err error) {
555	var tv Timeval
556	err = Gettimeofday(&tv)
557	if err != nil {
558		return 0, err
559	}
560	if t != nil {
561		*t = Time_t(tv.Sec)
562	}
563	return Time_t(tv.Sec), nil
564}
565
566func setTimespec(sec, nsec int64) Timespec {
567	return Timespec{Sec: sec, Nsec: nsec}
568}
569
570func setTimeval(sec, usec int64) Timeval { //fix
571	return Timeval{Sec: sec, Usec: usec}
572}
573
574//sysnb pipe(p *[2]_C_int) (err error)
575
576func Pipe(p []int) (err error) {
577	if len(p) != 2 {
578		return EINVAL
579	}
580	var pp [2]_C_int
581	err = pipe(&pp)
582	p[0] = int(pp[0])
583	p[1] = int(pp[1])
584	return
585}
586
587//sys	utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A
588
589func Utimes(path string, tv []Timeval) (err error) {
590	if len(tv) != 2 {
591		return EINVAL
592	}
593	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
594}
595
596func UtimesNano(path string, ts []Timespec) error {
597	if len(ts) != 2 {
598		return EINVAL
599	}
600	// Not as efficient as it could be because Timespec and
601	// Timeval have different types in the different OSes
602	tv := [2]Timeval{
603		NsecToTimeval(TimespecToNsec(ts[0])),
604		NsecToTimeval(TimespecToNsec(ts[1])),
605	}
606	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
607}
608
609func Getsockname(fd int) (sa Sockaddr, err error) {
610	var rsa RawSockaddrAny
611	var len _Socklen = SizeofSockaddrAny
612	if err = getsockname(fd, &rsa, &len); err != nil {
613		return
614	}
615	// TODO(neeilan) : Remove this 0 ( added to get sys/unix compiling on z/OS )
616	return anyToSockaddr(0, &rsa)
617}
618
619const (
620	// identifier constants
621	nwmHeaderIdentifier    = 0xd5e6d4c8
622	nwmFilterIdentifier    = 0xd5e6d4c6
623	nwmTCPConnIdentifier   = 0xd5e6d4c3
624	nwmRecHeaderIdentifier = 0xd5e6d4d9
625	nwmIPStatsIdentifier   = 0xd5e6d4c9d7e2e340
626	nwmIPGStatsIdentifier  = 0xd5e6d4c9d7c7e2e3
627	nwmTCPStatsIdentifier  = 0xd5e6d4e3c3d7e2e3
628	nwmUDPStatsIdentifier  = 0xd5e6d4e4c4d7e2e3
629	nwmICMPGStatsEntry     = 0xd5e6d4c9c3d4d7c7
630	nwmICMPTStatsEntry     = 0xd5e6d4c9c3d4d7e3
631
632	// nwmHeader constants
633	nwmVersion1   = 1
634	nwmVersion2   = 2
635	nwmCurrentVer = 2
636
637	nwmTCPConnType     = 1
638	nwmGlobalStatsType = 14
639
640	// nwmFilter constants
641	nwmFilterLclAddrMask = 0x20000000 // Local address
642	nwmFilterSrcAddrMask = 0x20000000 // Source address
643	nwmFilterLclPortMask = 0x10000000 // Local port
644	nwmFilterSrcPortMask = 0x10000000 // Source port
645
646	// nwmConnEntry constants
647	nwmTCPStateClosed   = 1
648	nwmTCPStateListen   = 2
649	nwmTCPStateSynSent  = 3
650	nwmTCPStateSynRcvd  = 4
651	nwmTCPStateEstab    = 5
652	nwmTCPStateFinWait1 = 6
653	nwmTCPStateFinWait2 = 7
654	nwmTCPStateClosWait = 8
655	nwmTCPStateLastAck  = 9
656	nwmTCPStateClosing  = 10
657	nwmTCPStateTimeWait = 11
658	nwmTCPStateDeletTCB = 12
659
660	// Existing constants on linux
661	BPF_TCP_CLOSE        = 1
662	BPF_TCP_LISTEN       = 2
663	BPF_TCP_SYN_SENT     = 3
664	BPF_TCP_SYN_RECV     = 4
665	BPF_TCP_ESTABLISHED  = 5
666	BPF_TCP_FIN_WAIT1    = 6
667	BPF_TCP_FIN_WAIT2    = 7
668	BPF_TCP_CLOSE_WAIT   = 8
669	BPF_TCP_LAST_ACK     = 9
670	BPF_TCP_CLOSING      = 10
671	BPF_TCP_TIME_WAIT    = 11
672	BPF_TCP_NEW_SYN_RECV = -1
673	BPF_TCP_MAX_STATES   = -2
674)
675
676type nwmTriplet struct {
677	offset uint32
678	length uint32
679	number uint32
680}
681
682type nwmQuadruplet struct {
683	offset uint32
684	length uint32
685	number uint32
686	match  uint32
687}
688
689type nwmHeader struct {
690	ident       uint32
691	length      uint32
692	version     uint16
693	nwmType     uint16
694	bytesNeeded uint32
695	options     uint32
696	_           [16]byte
697	inputDesc   nwmTriplet
698	outputDesc  nwmQuadruplet
699}
700
701type nwmFilter struct {
702	ident         uint32
703	flags         uint32
704	resourceName  [8]byte
705	resourceId    uint32
706	listenerId    uint32
707	local         [28]byte // union of sockaddr4 and sockaddr6
708	remote        [28]byte // union of sockaddr4 and sockaddr6
709	_             uint16
710	_             uint16
711	asid          uint16
712	_             [2]byte
713	tnLuName      [8]byte
714	tnMonGrp      uint32
715	tnAppl        [8]byte
716	applData      [40]byte
717	nInterface    [16]byte
718	dVipa         [16]byte
719	dVipaPfx      uint16
720	dVipaPort     uint16
721	dVipaFamily   byte
722	_             [3]byte
723	destXCF       [16]byte
724	destXCFPfx    uint16
725	destXCFFamily byte
726	_             [1]byte
727	targIP        [16]byte
728	targIPPfx     uint16
729	targIPFamily  byte
730	_             [1]byte
731	_             [20]byte
732}
733
734type nwmRecHeader struct {
735	ident  uint32
736	length uint32
737	number byte
738	_      [3]byte
739}
740
741type nwmTCPStatsEntry struct {
742	ident             uint64
743	currEstab         uint32
744	activeOpened      uint32
745	passiveOpened     uint32
746	connClosed        uint32
747	estabResets       uint32
748	attemptFails      uint32
749	passiveDrops      uint32
750	timeWaitReused    uint32
751	inSegs            uint64
752	predictAck        uint32
753	predictData       uint32
754	inDupAck          uint32
755	inBadSum          uint32
756	inBadLen          uint32
757	inShort           uint32
758	inDiscOldTime     uint32
759	inAllBeforeWin    uint32
760	inSomeBeforeWin   uint32
761	inAllAfterWin     uint32
762	inSomeAfterWin    uint32
763	inOutOfOrder      uint32
764	inAfterClose      uint32
765	inWinProbes       uint32
766	inWinUpdates      uint32
767	outWinUpdates     uint32
768	outSegs           uint64
769	outDelayAcks      uint32
770	outRsts           uint32
771	retransSegs       uint32
772	retransTimeouts   uint32
773	retransDrops      uint32
774	pmtuRetrans       uint32
775	pmtuErrors        uint32
776	outWinProbes      uint32
777	probeDrops        uint32
778	keepAliveProbes   uint32
779	keepAliveDrops    uint32
780	finwait2Drops     uint32
781	acceptCount       uint64
782	inBulkQSegs       uint64
783	inDiscards        uint64
784	connFloods        uint32
785	connStalls        uint32
786	cfgEphemDef       uint16
787	ephemInUse        uint16
788	ephemHiWater      uint16
789	flags             byte
790	_                 [1]byte
791	ephemExhaust      uint32
792	smcRCurrEstabLnks uint32
793	smcRLnkActTimeOut uint32
794	smcRActLnkOpened  uint32
795	smcRPasLnkOpened  uint32
796	smcRLnksClosed    uint32
797	smcRCurrEstab     uint32
798	smcRActiveOpened  uint32
799	smcRPassiveOpened uint32
800	smcRConnClosed    uint32
801	smcRInSegs        uint64
802	smcROutSegs       uint64
803	smcRInRsts        uint32
804	smcROutRsts       uint32
805	smcDCurrEstabLnks uint32
806	smcDActLnkOpened  uint32
807	smcDPasLnkOpened  uint32
808	smcDLnksClosed    uint32
809	smcDCurrEstab     uint32
810	smcDActiveOpened  uint32
811	smcDPassiveOpened uint32
812	smcDConnClosed    uint32
813	smcDInSegs        uint64
814	smcDOutSegs       uint64
815	smcDInRsts        uint32
816	smcDOutRsts       uint32
817}
818
819type nwmConnEntry struct {
820	ident             uint32
821	local             [28]byte // union of sockaddr4 and sockaddr6
822	remote            [28]byte // union of sockaddr4 and sockaddr6
823	startTime         [8]byte  // uint64, changed to prevent padding from being inserted
824	lastActivity      [8]byte  // uint64
825	bytesIn           [8]byte  // uint64
826	bytesOut          [8]byte  // uint64
827	inSegs            [8]byte  // uint64
828	outSegs           [8]byte  // uint64
829	state             uint16
830	activeOpen        byte
831	flag01            byte
832	outBuffered       uint32
833	inBuffered        uint32
834	maxSndWnd         uint32
835	reXmtCount        uint32
836	congestionWnd     uint32
837	ssThresh          uint32
838	roundTripTime     uint32
839	roundTripVar      uint32
840	sendMSS           uint32
841	sndWnd            uint32
842	rcvBufSize        uint32
843	sndBufSize        uint32
844	outOfOrderCount   uint32
845	lcl0WindowCount   uint32
846	rmt0WindowCount   uint32
847	dupacks           uint32
848	flag02            byte
849	sockOpt6Cont      byte
850	asid              uint16
851	resourceName      [8]byte
852	resourceId        uint32
853	subtask           uint32
854	sockOpt           byte
855	sockOpt6          byte
856	clusterConnFlag   byte
857	proto             byte
858	targetAppl        [8]byte
859	luName            [8]byte
860	clientUserId      [8]byte
861	logMode           [8]byte
862	timeStamp         uint32
863	timeStampAge      uint32
864	serverResourceId  uint32
865	intfName          [16]byte
866	ttlsStatPol       byte
867	ttlsStatConn      byte
868	ttlsSSLProt       uint16
869	ttlsNegCiph       [2]byte
870	ttlsSecType       byte
871	ttlsFIPS140Mode   byte
872	ttlsUserID        [8]byte
873	applData          [40]byte
874	inOldestTime      [8]byte // uint64
875	outOldestTime     [8]byte // uint64
876	tcpTrustedPartner byte
877	_                 [3]byte
878	bulkDataIntfName  [16]byte
879	ttlsNegCiph4      [4]byte
880	smcReason         uint32
881	lclSMCLinkId      uint32
882	rmtSMCLinkId      uint32
883	smcStatus         byte
884	smcFlags          byte
885	_                 [2]byte
886	rcvWnd            uint32
887	lclSMCBufSz       uint32
888	rmtSMCBufSz       uint32
889	ttlsSessID        [32]byte
890	ttlsSessIDLen     int16
891	_                 [1]byte
892	smcDStatus        byte
893	smcDReason        uint32
894}
895
896var svcNameTable [][]byte = [][]byte{
897	[]byte("\xc5\xe9\xc2\xd5\xd4\xc9\xc6\xf4"), // svc_EZBNMIF4
898}
899
900const (
901	svc_EZBNMIF4 = 0
902)
903
904func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) {
905	jobname := []byte("\x5c\x40\x40\x40\x40\x40\x40\x40") // "*"
906	responseBuffer := [4096]byte{0}
907	var bufferAlet, reasonCode uint32 = 0, 0
908	var bufferLen, returnValue, returnCode int32 = 4096, 0, 0
909
910	dsa := [18]uint64{0}
911	var argv [7]unsafe.Pointer
912	argv[0] = unsafe.Pointer(&jobname[0])
913	argv[1] = unsafe.Pointer(&responseBuffer[0])
914	argv[2] = unsafe.Pointer(&bufferAlet)
915	argv[3] = unsafe.Pointer(&bufferLen)
916	argv[4] = unsafe.Pointer(&returnValue)
917	argv[5] = unsafe.Pointer(&returnCode)
918	argv[6] = unsafe.Pointer(&reasonCode)
919
920	request := (*struct {
921		header nwmHeader
922		filter nwmFilter
923	})(unsafe.Pointer(&responseBuffer[0]))
924
925	EZBNMIF4 := svcLoad(&svcNameTable[svc_EZBNMIF4][0])
926	if EZBNMIF4 == nil {
927		return nil, errnoErr(EINVAL)
928	}
929
930	// GetGlobalStats EZBNMIF4 call
931	request.header.ident = nwmHeaderIdentifier
932	request.header.length = uint32(unsafe.Sizeof(request.header))
933	request.header.version = nwmCurrentVer
934	request.header.nwmType = nwmGlobalStatsType
935	request.header.options = 0x80000000
936
937	svcCall(EZBNMIF4, &argv[0], &dsa[0])
938
939	// outputDesc field is filled by EZBNMIF4 on success
940	if returnCode != 0 || request.header.outputDesc.offset == 0 {
941		return nil, errnoErr(EINVAL)
942	}
943
944	// Check that EZBNMIF4 returned a nwmRecHeader
945	recHeader := (*nwmRecHeader)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
946	if recHeader.ident != nwmRecHeaderIdentifier {
947		return nil, errnoErr(EINVAL)
948	}
949
950	// Parse nwmTriplets to get offsets of returned entries
951	var sections []*uint64
952	var sectionDesc *nwmTriplet = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[0]))
953	for i := uint32(0); i < uint32(recHeader.number); i++ {
954		offset := request.header.outputDesc.offset + uint32(unsafe.Sizeof(*recHeader)) + i*uint32(unsafe.Sizeof(*sectionDesc))
955		sectionDesc = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[offset]))
956		for j := uint32(0); j < sectionDesc.number; j++ {
957			offset = request.header.outputDesc.offset + sectionDesc.offset + j*sectionDesc.length
958			sections = append(sections, (*uint64)(unsafe.Pointer(&responseBuffer[offset])))
959		}
960	}
961
962	// Find nwmTCPStatsEntry in returned entries
963	var tcpStats *nwmTCPStatsEntry = nil
964	for _, ptr := range sections {
965		switch *ptr {
966		case nwmTCPStatsIdentifier:
967			if tcpStats != nil {
968				return nil, errnoErr(EINVAL)
969			}
970			tcpStats = (*nwmTCPStatsEntry)(unsafe.Pointer(ptr))
971		case nwmIPStatsIdentifier:
972		case nwmIPGStatsIdentifier:
973		case nwmUDPStatsIdentifier:
974		case nwmICMPGStatsEntry:
975		case nwmICMPTStatsEntry:
976		default:
977			return nil, errnoErr(EINVAL)
978		}
979	}
980	if tcpStats == nil {
981		return nil, errnoErr(EINVAL)
982	}
983
984	// GetConnectionDetail EZBNMIF4 call
985	responseBuffer = [4096]byte{0}
986	dsa = [18]uint64{0}
987	bufferAlet, reasonCode = 0, 0
988	bufferLen, returnValue, returnCode = 4096, 0, 0
989	nameptr := (*uint32)(unsafe.Pointer(uintptr(0x21c))) // Get jobname of current process
990	nameptr = (*uint32)(unsafe.Pointer(uintptr(*nameptr + 12)))
991	argv[0] = unsafe.Pointer(uintptr(*nameptr))
992
993	request.header.ident = nwmHeaderIdentifier
994	request.header.length = uint32(unsafe.Sizeof(request.header))
995	request.header.version = nwmCurrentVer
996	request.header.nwmType = nwmTCPConnType
997	request.header.options = 0x80000000
998
999	request.filter.ident = nwmFilterIdentifier
1000
1001	var localSockaddr RawSockaddrAny
1002	socklen := _Socklen(SizeofSockaddrAny)
1003	err := getsockname(fd, &localSockaddr, &socklen)
1004	if err != nil {
1005		return nil, errnoErr(EINVAL)
1006	}
1007	if localSockaddr.Addr.Family == AF_INET {
1008		localSockaddr := (*RawSockaddrInet4)(unsafe.Pointer(&localSockaddr.Addr))
1009		localSockFilter := (*RawSockaddrInet4)(unsafe.Pointer(&request.filter.local[0]))
1010		localSockFilter.Family = AF_INET
1011		var i int
1012		for i = 0; i < 4; i++ {
1013			if localSockaddr.Addr[i] != 0 {
1014				break
1015			}
1016		}
1017		if i != 4 {
1018			request.filter.flags |= nwmFilterLclAddrMask
1019			for i = 0; i < 4; i++ {
1020				localSockFilter.Addr[i] = localSockaddr.Addr[i]
1021			}
1022		}
1023		if localSockaddr.Port != 0 {
1024			request.filter.flags |= nwmFilterLclPortMask
1025			localSockFilter.Port = localSockaddr.Port
1026		}
1027	} else if localSockaddr.Addr.Family == AF_INET6 {
1028		localSockaddr := (*RawSockaddrInet6)(unsafe.Pointer(&localSockaddr.Addr))
1029		localSockFilter := (*RawSockaddrInet6)(unsafe.Pointer(&request.filter.local[0]))
1030		localSockFilter.Family = AF_INET6
1031		var i int
1032		for i = 0; i < 16; i++ {
1033			if localSockaddr.Addr[i] != 0 {
1034				break
1035			}
1036		}
1037		if i != 16 {
1038			request.filter.flags |= nwmFilterLclAddrMask
1039			for i = 0; i < 16; i++ {
1040				localSockFilter.Addr[i] = localSockaddr.Addr[i]
1041			}
1042		}
1043		if localSockaddr.Port != 0 {
1044			request.filter.flags |= nwmFilterLclPortMask
1045			localSockFilter.Port = localSockaddr.Port
1046		}
1047	}
1048
1049	svcCall(EZBNMIF4, &argv[0], &dsa[0])
1050
1051	// outputDesc field is filled by EZBNMIF4 on success
1052	if returnCode != 0 || request.header.outputDesc.offset == 0 {
1053		return nil, errnoErr(EINVAL)
1054	}
1055
1056	// Check that EZBNMIF4 returned a nwmConnEntry
1057	conn := (*nwmConnEntry)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
1058	if conn.ident != nwmTCPConnIdentifier {
1059		return nil, errnoErr(EINVAL)
1060	}
1061
1062	// Copy data from the returned data structures into tcpInfo
1063	// Stats from nwmConnEntry are specific to that connection.
1064	// Stats from nwmTCPStatsEntry are global (to the interface?)
1065	// Fields may not be an exact match. Some fields have no equivalent.
1066	var tcpinfo TCPInfo
1067	tcpinfo.State = uint8(conn.state)
1068	tcpinfo.Ca_state = 0 // dummy
1069	tcpinfo.Retransmits = uint8(tcpStats.retransSegs)
1070	tcpinfo.Probes = uint8(tcpStats.outWinProbes)
1071	tcpinfo.Backoff = 0 // dummy
1072	tcpinfo.Options = 0 // dummy
1073	tcpinfo.Rto = tcpStats.retransTimeouts
1074	tcpinfo.Ato = tcpStats.outDelayAcks
1075	tcpinfo.Snd_mss = conn.sendMSS
1076	tcpinfo.Rcv_mss = conn.sendMSS // dummy
1077	tcpinfo.Unacked = 0            // dummy
1078	tcpinfo.Sacked = 0             // dummy
1079	tcpinfo.Lost = 0               // dummy
1080	tcpinfo.Retrans = conn.reXmtCount
1081	tcpinfo.Fackets = 0 // dummy
1082	tcpinfo.Last_data_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.lastActivity[0])))
1083	tcpinfo.Last_ack_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.outOldestTime[0])))
1084	tcpinfo.Last_data_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
1085	tcpinfo.Last_ack_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
1086	tcpinfo.Pmtu = conn.sendMSS // dummy, NWMIfRouteMtu is a candidate
1087	tcpinfo.Rcv_ssthresh = conn.ssThresh
1088	tcpinfo.Rtt = conn.roundTripTime
1089	tcpinfo.Rttvar = conn.roundTripVar
1090	tcpinfo.Snd_ssthresh = conn.ssThresh // dummy
1091	tcpinfo.Snd_cwnd = conn.congestionWnd
1092	tcpinfo.Advmss = conn.sendMSS        // dummy
1093	tcpinfo.Reordering = 0               // dummy
1094	tcpinfo.Rcv_rtt = conn.roundTripTime // dummy
1095	tcpinfo.Rcv_space = conn.sendMSS     // dummy
1096	tcpinfo.Total_retrans = conn.reXmtCount
1097
1098	svcUnload(&svcNameTable[svc_EZBNMIF4][0], EZBNMIF4)
1099
1100	return &tcpinfo, nil
1101}
1102
1103// GetsockoptString returns the string value of the socket option opt for the
1104// socket associated with fd at the given socket level.
1105func GetsockoptString(fd, level, opt int) (string, error) {
1106	buf := make([]byte, 256)
1107	vallen := _Socklen(len(buf))
1108	err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
1109	if err != nil {
1110		return "", err
1111	}
1112
1113	return string(buf[:vallen-1]), nil
1114}
1115
1116func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
1117	var msg Msghdr
1118	var rsa RawSockaddrAny
1119	msg.Name = (*byte)(unsafe.Pointer(&rsa))
1120	msg.Namelen = SizeofSockaddrAny
1121	var iov Iovec
1122	if len(p) > 0 {
1123		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
1124		iov.SetLen(len(p))
1125	}
1126	var dummy byte
1127	if len(oob) > 0 {
1128		// receive at least one normal byte
1129		if len(p) == 0 {
1130			iov.Base = &dummy
1131			iov.SetLen(1)
1132		}
1133		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
1134		msg.SetControllen(len(oob))
1135	}
1136	msg.Iov = &iov
1137	msg.Iovlen = 1
1138	if n, err = recvmsg(fd, &msg, flags); err != nil {
1139		return
1140	}
1141	oobn = int(msg.Controllen)
1142	recvflags = int(msg.Flags)
1143	// source address is only specified if the socket is unconnected
1144	if rsa.Addr.Family != AF_UNSPEC {
1145		// TODO(neeilan): Remove 0 arg added to get this compiling on z/OS
1146		from, err = anyToSockaddr(0, &rsa)
1147	}
1148	return
1149}
1150
1151func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
1152	_, err = SendmsgN(fd, p, oob, to, flags)
1153	return
1154}
1155
1156func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
1157	var ptr unsafe.Pointer
1158	var salen _Socklen
1159	if to != nil {
1160		var err error
1161		ptr, salen, err = to.sockaddr()
1162		if err != nil {
1163			return 0, err
1164		}
1165	}
1166	var msg Msghdr
1167	msg.Name = (*byte)(unsafe.Pointer(ptr))
1168	msg.Namelen = int32(salen)
1169	var iov Iovec
1170	if len(p) > 0 {
1171		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
1172		iov.SetLen(len(p))
1173	}
1174	var dummy byte
1175	if len(oob) > 0 {
1176		// send at least one normal byte
1177		if len(p) == 0 {
1178			iov.Base = &dummy
1179			iov.SetLen(1)
1180		}
1181		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
1182		msg.SetControllen(len(oob))
1183	}
1184	msg.Iov = &iov
1185	msg.Iovlen = 1
1186	if n, err = sendmsg(fd, &msg, flags); err != nil {
1187		return 0, err
1188	}
1189	if len(oob) > 0 && len(p) == 0 {
1190		n = 0
1191	}
1192	return n, nil
1193}
1194
1195func Opendir(name string) (uintptr, error) {
1196	p, err := BytePtrFromString(name)
1197	if err != nil {
1198		return 0, err
1199	}
1200	dir, _, e := syscall_syscall(SYS___OPENDIR_A, uintptr(unsafe.Pointer(p)), 0, 0)
1201	runtime.KeepAlive(unsafe.Pointer(p))
1202	if e != 0 {
1203		err = errnoErr(e)
1204	}
1205	return dir, err
1206}
1207
1208// clearsyscall.Errno resets the errno value to 0.
1209func clearErrno()
1210
1211func Readdir(dir uintptr) (*Dirent, error) {
1212	var ent Dirent
1213	var res uintptr
1214	// __readdir_r_a returns errno at the end of the directory stream, rather than 0.
1215	// Therefore to avoid false positives we clear errno before calling it.
1216
1217	// TODO(neeilan): Commented this out to get sys/unix compiling on z/OS. Uncomment and fix. Error: "undefined: clearsyscall"
1218	//clearsyscall.Errno() // TODO(mundaym): check pre-emption rules.
1219
1220	e, _, _ := syscall_syscall(SYS___READDIR_R_A, dir, uintptr(unsafe.Pointer(&ent)), uintptr(unsafe.Pointer(&res)))
1221	var err error
1222	if e != 0 {
1223		err = errnoErr(Errno(e))
1224	}
1225	if res == 0 {
1226		return nil, err
1227	}
1228	return &ent, err
1229}
1230
1231func Closedir(dir uintptr) error {
1232	_, _, e := syscall_syscall(SYS_CLOSEDIR, dir, 0, 0)
1233	if e != 0 {
1234		return errnoErr(e)
1235	}
1236	return nil
1237}
1238
1239func Seekdir(dir uintptr, pos int) {
1240	_, _, _ = syscall_syscall(SYS_SEEKDIR, dir, uintptr(pos), 0)
1241}
1242
1243func Telldir(dir uintptr) (int, error) {
1244	p, _, e := syscall_syscall(SYS_TELLDIR, dir, 0, 0)
1245	pos := int(p)
1246	if pos == -1 {
1247		return pos, errnoErr(e)
1248	}
1249	return pos, nil
1250}
1251
1252// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
1253func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
1254	// struct flock is packed on z/OS. We can't emulate that in Go so
1255	// instead we pack it here.
1256	var flock [24]byte
1257	*(*int16)(unsafe.Pointer(&flock[0])) = lk.Type
1258	*(*int16)(unsafe.Pointer(&flock[2])) = lk.Whence
1259	*(*int64)(unsafe.Pointer(&flock[4])) = lk.Start
1260	*(*int64)(unsafe.Pointer(&flock[12])) = lk.Len
1261	*(*int32)(unsafe.Pointer(&flock[20])) = lk.Pid
1262	_, _, errno := syscall_syscall(SYS_FCNTL, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock)))
1263	lk.Type = *(*int16)(unsafe.Pointer(&flock[0]))
1264	lk.Whence = *(*int16)(unsafe.Pointer(&flock[2]))
1265	lk.Start = *(*int64)(unsafe.Pointer(&flock[4]))
1266	lk.Len = *(*int64)(unsafe.Pointer(&flock[12]))
1267	lk.Pid = *(*int32)(unsafe.Pointer(&flock[20]))
1268	if errno == 0 {
1269		return nil
1270	}
1271	return errno
1272}
1273
1274func Flock(fd int, how int) error {
1275
1276	var flock_type int16
1277	var fcntl_cmd int
1278
1279	switch how {
1280	case LOCK_SH | LOCK_NB:
1281		flock_type = F_RDLCK
1282		fcntl_cmd = F_SETLK
1283	case LOCK_EX | LOCK_NB:
1284		flock_type = F_WRLCK
1285		fcntl_cmd = F_SETLK
1286	case LOCK_EX:
1287		flock_type = F_WRLCK
1288		fcntl_cmd = F_SETLKW
1289	case LOCK_UN:
1290		flock_type = F_UNLCK
1291		fcntl_cmd = F_SETLKW
1292	default:
1293	}
1294
1295	flock := Flock_t{
1296		Type:   int16(flock_type),
1297		Whence: int16(0),
1298		Start:  int64(0),
1299		Len:    int64(0),
1300		Pid:    int32(Getppid()),
1301	}
1302
1303	err := FcntlFlock(uintptr(fd), fcntl_cmd, &flock)
1304	return err
1305}
1306
1307func Mlock(b []byte) (err error) {
1308	_, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
1309	if e1 != 0 {
1310		err = errnoErr(e1)
1311	}
1312	return
1313}
1314
1315func Mlock2(b []byte, flags int) (err error) {
1316	_, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
1317	if e1 != 0 {
1318		err = errnoErr(e1)
1319	}
1320	return
1321}
1322
1323func Mlockall(flags int) (err error) {
1324	_, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
1325	if e1 != 0 {
1326		err = errnoErr(e1)
1327	}
1328	return
1329}
1330
1331func Munlock(b []byte) (err error) {
1332	_, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0)
1333	if e1 != 0 {
1334		err = errnoErr(e1)
1335	}
1336	return
1337}
1338
1339func Munlockall() (err error) {
1340	_, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0)
1341	if e1 != 0 {
1342		err = errnoErr(e1)
1343	}
1344	return
1345}
1346
1347func ClockGettime(clockid int32, ts *Timespec) error {
1348
1349	var ticks_per_sec uint32 = 100 //TODO(kenan): value is currently hardcoded; need sysconf() call otherwise
1350	var nsec_per_sec int64 = 1000000000
1351
1352	if ts == nil {
1353		return EFAULT
1354	}
1355	if clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC {
1356		var nanotime int64 = runtime.Nanotime1()
1357		ts.Sec = nanotime / nsec_per_sec
1358		ts.Nsec = nanotime % nsec_per_sec
1359	} else if clockid == CLOCK_PROCESS_CPUTIME_ID || clockid == CLOCK_THREAD_CPUTIME_ID {
1360		var tm Tms
1361		_, err := Times(&tm)
1362		if err != nil {
1363			return EFAULT
1364		}
1365		ts.Sec = int64(tm.Utime / ticks_per_sec)
1366		ts.Nsec = int64(tm.Utime) * nsec_per_sec / int64(ticks_per_sec)
1367	} else {
1368		return EINVAL
1369	}
1370	return nil
1371}
1372
1373func Statfs(path string, stat *Statfs_t) (err error) {
1374	fd, err := open(path, O_RDONLY, 0)
1375	defer Close(fd)
1376	if err != nil {
1377		return err
1378	}
1379	return Fstatfs(fd, stat)
1380}
1381
1382var (
1383	Stdin  = 0
1384	Stdout = 1
1385	Stderr = 2
1386)
1387
1388// Do the interface allocations only once for common
1389// Errno values.
1390var (
1391	errEAGAIN error = syscall.EAGAIN
1392	errEINVAL error = syscall.EINVAL
1393	errENOENT error = syscall.ENOENT
1394)
1395
1396var (
1397	signalNameMapOnce sync.Once
1398	signalNameMap     map[string]syscall.Signal
1399)
1400
1401// errnoErr returns common boxed Errno values, to prevent
1402// allocations at runtime.
1403func errnoErr(e Errno) error {
1404	switch e {
1405	case 0:
1406		return nil
1407	case EAGAIN:
1408		return errEAGAIN
1409	case EINVAL:
1410		return errEINVAL
1411	case ENOENT:
1412		return errENOENT
1413	}
1414	return e
1415}
1416
1417// ErrnoName returns the error name for error number e.
1418func ErrnoName(e Errno) string {
1419	i := sort.Search(len(errorList), func(i int) bool {
1420		return errorList[i].num >= e
1421	})
1422	if i < len(errorList) && errorList[i].num == e {
1423		return errorList[i].name
1424	}
1425	return ""
1426}
1427
1428// SignalName returns the signal name for signal number s.
1429func SignalName(s syscall.Signal) string {
1430	i := sort.Search(len(signalList), func(i int) bool {
1431		return signalList[i].num >= s
1432	})
1433	if i < len(signalList) && signalList[i].num == s {
1434		return signalList[i].name
1435	}
1436	return ""
1437}
1438
1439// SignalNum returns the syscall.Signal for signal named s,
1440// or 0 if a signal with such name is not found.
1441// The signal name should start with "SIG".
1442func SignalNum(s string) syscall.Signal {
1443	signalNameMapOnce.Do(func() {
1444		signalNameMap = make(map[string]syscall.Signal, len(signalList))
1445		for _, signal := range signalList {
1446			signalNameMap[signal.name] = signal.num
1447		}
1448	})
1449	return signalNameMap[s]
1450}
1451
1452// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
1453func clen(n []byte) int {
1454	i := bytes.IndexByte(n, 0)
1455	if i == -1 {
1456		i = len(n)
1457	}
1458	return i
1459}
1460
1461// Mmap manager, for use by operating system-specific implementations.
1462
1463type mmapper struct {
1464	sync.Mutex
1465	active map[*byte][]byte // active mappings; key is last byte in mapping
1466	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
1467	munmap func(addr uintptr, length uintptr) error
1468}
1469
1470func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
1471	if length <= 0 {
1472		return nil, EINVAL
1473	}
1474
1475	// Map the requested memory.
1476	addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
1477	if errno != nil {
1478		return nil, errno
1479	}
1480
1481	// Slice memory layout
1482	var sl = struct {
1483		addr uintptr
1484		len  int
1485		cap  int
1486	}{addr, length, length}
1487
1488	// Use unsafe to turn sl into a []byte.
1489	b := *(*[]byte)(unsafe.Pointer(&sl))
1490
1491	// Register mapping in m and return it.
1492	p := &b[cap(b)-1]
1493	m.Lock()
1494	defer m.Unlock()
1495	m.active[p] = b
1496	return b, nil
1497}
1498
1499func (m *mmapper) Munmap(data []byte) (err error) {
1500	if len(data) == 0 || len(data) != cap(data) {
1501		return EINVAL
1502	}
1503
1504	// Find the base of the mapping.
1505	p := &data[cap(data)-1]
1506	m.Lock()
1507	defer m.Unlock()
1508	b := m.active[p]
1509	if b == nil || &b[0] != &data[0] {
1510		return EINVAL
1511	}
1512
1513	// Unmap the memory and update m.
1514	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
1515		return errno
1516	}
1517	delete(m.active, p)
1518	return nil
1519}
1520
1521func Read(fd int, p []byte) (n int, err error) {
1522	n, err = read(fd, p)
1523	if raceenabled {
1524		if n > 0 {
1525			raceWriteRange(unsafe.Pointer(&p[0]), n)
1526		}
1527		if err == nil {
1528			raceAcquire(unsafe.Pointer(&ioSync))
1529		}
1530	}
1531	return
1532}
1533
1534func Write(fd int, p []byte) (n int, err error) {
1535	if raceenabled {
1536		raceReleaseMerge(unsafe.Pointer(&ioSync))
1537	}
1538	n, err = write(fd, p)
1539	if raceenabled && n > 0 {
1540		raceReadRange(unsafe.Pointer(&p[0]), n)
1541	}
1542	return
1543}
1544
1545// For testing: clients can set this flag to force
1546// creation of IPv6 sockets to return EAFNOSUPPORT.
1547var SocketDisableIPv6 bool
1548
1549// Sockaddr represents a socket address.
1550type Sockaddr interface {
1551	sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs
1552}
1553
1554// SockaddrInet4 implements the Sockaddr interface for AF_INET type sockets.
1555type SockaddrInet4 struct {
1556	Port int
1557	Addr [4]byte
1558	raw  RawSockaddrInet4
1559}
1560
1561// SockaddrInet6 implements the Sockaddr interface for AF_INET6 type sockets.
1562type SockaddrInet6 struct {
1563	Port   int
1564	ZoneId uint32
1565	Addr   [16]byte
1566	raw    RawSockaddrInet6
1567}
1568
1569// SockaddrUnix implements the Sockaddr interface for AF_UNIX type sockets.
1570type SockaddrUnix struct {
1571	Name string
1572	raw  RawSockaddrUnix
1573}
1574
1575func Bind(fd int, sa Sockaddr) (err error) {
1576	ptr, n, err := sa.sockaddr()
1577	if err != nil {
1578		return err
1579	}
1580	return bind(fd, ptr, n)
1581}
1582
1583func Connect(fd int, sa Sockaddr) (err error) {
1584	ptr, n, err := sa.sockaddr()
1585	if err != nil {
1586		return err
1587	}
1588	return connect(fd, ptr, n)
1589}
1590
1591func Getpeername(fd int) (sa Sockaddr, err error) {
1592	var rsa RawSockaddrAny
1593	var len _Socklen = SizeofSockaddrAny
1594	if err = getpeername(fd, &rsa, &len); err != nil {
1595		return
1596	}
1597	return anyToSockaddr(fd, &rsa)
1598}
1599
1600func GetsockoptByte(fd, level, opt int) (value byte, err error) {
1601	var n byte
1602	vallen := _Socklen(1)
1603	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
1604	return n, err
1605}
1606
1607func GetsockoptInt(fd, level, opt int) (value int, err error) {
1608	var n int32
1609	vallen := _Socklen(4)
1610	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
1611	return int(n), err
1612}
1613
1614func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
1615	vallen := _Socklen(4)
1616	err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
1617	return value, err
1618}
1619
1620func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
1621	var value IPMreq
1622	vallen := _Socklen(SizeofIPMreq)
1623	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
1624	return &value, err
1625}
1626
1627func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
1628	var value IPv6Mreq
1629	vallen := _Socklen(SizeofIPv6Mreq)
1630	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
1631	return &value, err
1632}
1633
1634func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) {
1635	var value IPv6MTUInfo
1636	vallen := _Socklen(SizeofIPv6MTUInfo)
1637	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
1638	return &value, err
1639}
1640
1641func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {
1642	var value ICMPv6Filter
1643	vallen := _Socklen(SizeofICMPv6Filter)
1644	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
1645	return &value, err
1646}
1647
1648func GetsockoptLinger(fd, level, opt int) (*Linger, error) {
1649	var linger Linger
1650	vallen := _Socklen(SizeofLinger)
1651	err := getsockopt(fd, level, opt, unsafe.Pointer(&linger), &vallen)
1652	return &linger, err
1653}
1654
1655func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) {
1656	var tv Timeval
1657	vallen := _Socklen(unsafe.Sizeof(tv))
1658	err := getsockopt(fd, level, opt, unsafe.Pointer(&tv), &vallen)
1659	return &tv, err
1660}
1661
1662func GetsockoptUint64(fd, level, opt int) (value uint64, err error) {
1663	var n uint64
1664	vallen := _Socklen(8)
1665	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
1666	return n, err
1667}
1668
1669func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
1670	var rsa RawSockaddrAny
1671	var len _Socklen = SizeofSockaddrAny
1672	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
1673		return
1674	}
1675	if rsa.Addr.Family != AF_UNSPEC {
1676		from, err = anyToSockaddr(fd, &rsa)
1677	}
1678	return
1679}
1680
1681func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
1682	ptr, n, err := to.sockaddr()
1683	if err != nil {
1684		return err
1685	}
1686	return sendto(fd, p, flags, ptr, n)
1687}
1688
1689func SetsockoptByte(fd, level, opt int, value byte) (err error) {
1690	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
1691}
1692
1693func SetsockoptInt(fd, level, opt int, value int) (err error) {
1694	var n = int32(value)
1695	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
1696}
1697
1698func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
1699	return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
1700}
1701
1702func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
1703	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq)
1704}
1705
1706func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
1707	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq)
1708}
1709
1710func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
1711	return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
1712}
1713
1714func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
1715	return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger)
1716}
1717
1718func SetsockoptString(fd, level, opt int, s string) (err error) {
1719	var p unsafe.Pointer
1720	if len(s) > 0 {
1721		p = unsafe.Pointer(&[]byte(s)[0])
1722	}
1723	return setsockopt(fd, level, opt, p, uintptr(len(s)))
1724}
1725
1726func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
1727	return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv))
1728}
1729
1730func SetsockoptUint64(fd, level, opt int, value uint64) (err error) {
1731	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 8)
1732}
1733
1734func Socket(domain, typ, proto int) (fd int, err error) {
1735	if domain == AF_INET6 && SocketDisableIPv6 {
1736		return -1, EAFNOSUPPORT
1737	}
1738	fd, err = socket(domain, typ, proto)
1739	return
1740}
1741
1742func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
1743	var fdx [2]int32
1744	err = socketpair(domain, typ, proto, &fdx)
1745	if err == nil {
1746		fd[0] = int(fdx[0])
1747		fd[1] = int(fdx[1])
1748	}
1749	return
1750}
1751
1752var ioSync int64
1753
1754func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
1755
1756func SetNonblock(fd int, nonblocking bool) (err error) {
1757	flag, err := fcntl(fd, F_GETFL, 0)
1758	if err != nil {
1759		return err
1760	}
1761	if nonblocking {
1762		flag |= O_NONBLOCK
1763	} else {
1764		flag &= ^O_NONBLOCK
1765	}
1766	_, err = fcntl(fd, F_SETFL, flag)
1767	return err
1768}
1769
1770// Exec calls execve(2), which replaces the calling executable in the process
1771// tree. argv0 should be the full path to an executable ("/bin/ls") and the
1772// executable name should also be the first argument in argv (["ls", "-l"]).
1773// envv are the environment variables that should be passed to the new
1774// process (["USER=go", "PWD=/tmp"]).
1775func Exec(argv0 string, argv []string, envv []string) error {
1776	return syscall.Exec(argv0, argv, envv)
1777}
1778
1779func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
1780	if needspace := 8 - len(fstype); needspace <= 0 {
1781		fstype = fstype[:8]
1782	} else {
1783		fstype += "        "[:needspace]
1784	}
1785	return mount_LE(target, source, fstype, uint32(flags), int32(len(data)), data)
1786}
1787
1788func Unmount(name string, mtm int) (err error) {
1789	// mountpoint is always a full path and starts with a '/'
1790	// check if input string is not a mountpoint but a filesystem name
1791	if name[0] != '/' {
1792		return unmount(name, mtm)
1793	}
1794	// treat name as mountpoint
1795	b2s := func(arr []byte) string {
1796		nulli := bytes.IndexByte(arr, 0)
1797		if nulli == -1 {
1798			return string(arr)
1799		} else {
1800			return string(arr[:nulli])
1801		}
1802	}
1803	var buffer struct {
1804		header W_Mnth
1805		fsinfo [64]W_Mntent
1806	}
1807	fsCount, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer)))
1808	if err != nil {
1809		return err
1810	}
1811	if fsCount == 0 {
1812		return EINVAL
1813	}
1814	for i := 0; i < fsCount; i++ {
1815		if b2s(buffer.fsinfo[i].Mountpoint[:]) == name {
1816			err = unmount(b2s(buffer.fsinfo[i].Fsname[:]), mtm)
1817			break
1818		}
1819	}
1820	return err
1821}
1822