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