syscall_zos_s390x.go

   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
   7// Many of the following syscalls are not available on all versions of z/OS.
   8// Some missing calls have legacy implementations/simulations but others
   9// will be missing completely. To achieve consistent failing behaviour on
  10// legacy systems, we first test the function pointer via a safeloading
  11// mechanism to see if the function exists on a given system. Then execution
  12// is branched to either continue the function call, or return an error.
  13
  14package unix
  15
  16import (
  17	"bytes"
  18	"fmt"
  19	"os"
  20	"reflect"
  21	"regexp"
  22	"runtime"
  23	"sort"
  24	"strings"
  25	"sync"
  26	"syscall"
  27	"unsafe"
  28)
  29
  30//go:noescape
  31func initZosLibVec()
  32
  33//go:noescape
  34func GetZosLibVec() uintptr
  35
  36func init() {
  37	initZosLibVec()
  38	r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACE\x00"))[0])))
  39	if r0 != 0 {
  40		n, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0)
  41		ZosTraceLevel = int(n)
  42		r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACEFD\x00"))[0])))
  43		if r0 != 0 {
  44			fd, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0)
  45			f := os.NewFile(fd, "zostracefile")
  46			if f != nil {
  47				ZosTracefile = f
  48			}
  49		}
  50
  51	}
  52}
  53
  54//go:noescape
  55func CallLeFuncWithErr(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno)
  56
  57//go:noescape
  58func CallLeFuncWithPtrReturn(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno)
  59
  60// -------------------------------
  61// pointer validity test
  62// good pointer returns 0
  63// bad pointer returns 1
  64//
  65//go:nosplit
  66func ptrtest(uintptr) uint64
  67
  68// Load memory at ptr location with error handling if the location is invalid
  69//
  70//go:noescape
  71func safeload(ptr uintptr) (value uintptr, error uintptr)
  72
  73const (
  74	entrypointLocationOffset = 8 // From function descriptor
  75
  76	xplinkEyecatcher   = 0x00c300c500c500f1 // ".C.E.E.1"
  77	eyecatcherOffset   = 16                 // From function entrypoint (negative)
  78	ppa1LocationOffset = 8                  // From function entrypoint (negative)
  79
  80	nameLenOffset = 0x14 // From PPA1 start
  81	nameOffset    = 0x16 // From PPA1 start
  82)
  83
  84func getPpaOffset(funcptr uintptr) int64 {
  85	entrypoint, err := safeload(funcptr + entrypointLocationOffset)
  86	if err != 0 {
  87		return -1
  88	}
  89
  90	// XPLink functions have ".C.E.E.1" as the first 8 bytes (EBCDIC)
  91	val, err := safeload(entrypoint - eyecatcherOffset)
  92	if err != 0 {
  93		return -1
  94	}
  95	if val != xplinkEyecatcher {
  96		return -1
  97	}
  98
  99	ppaoff, err := safeload(entrypoint - ppa1LocationOffset)
 100	if err != 0 {
 101		return -1
 102	}
 103
 104	ppaoff >>= 32
 105	return int64(ppaoff)
 106}
 107
 108//-------------------------------
 109// function descriptor pointer validity test
 110// good pointer returns 0
 111// bad pointer returns 1
 112
 113// TODO: currently mksyscall_zos_s390x.go generate empty string for funcName
 114// have correct funcName pass to the funcptrtest function
 115func funcptrtest(funcptr uintptr, funcName string) uint64 {
 116	entrypoint, err := safeload(funcptr + entrypointLocationOffset)
 117	if err != 0 {
 118		return 1
 119	}
 120
 121	ppaoff := getPpaOffset(funcptr)
 122	if ppaoff == -1 {
 123		return 1
 124	}
 125
 126	// PPA1 offset value is from the start of the entire function block, not the entrypoint
 127	ppa1 := (entrypoint - eyecatcherOffset) + uintptr(ppaoff)
 128
 129	nameLen, err := safeload(ppa1 + nameLenOffset)
 130	if err != 0 {
 131		return 1
 132	}
 133
 134	nameLen >>= 48
 135	if nameLen > 128 {
 136		return 1
 137	}
 138
 139	// no function name input to argument end here
 140	if funcName == "" {
 141		return 0
 142	}
 143
 144	var funcname [128]byte
 145	for i := 0; i < int(nameLen); i += 8 {
 146		v, err := safeload(ppa1 + nameOffset + uintptr(i))
 147		if err != 0 {
 148			return 1
 149		}
 150		funcname[i] = byte(v >> 56)
 151		funcname[i+1] = byte(v >> 48)
 152		funcname[i+2] = byte(v >> 40)
 153		funcname[i+3] = byte(v >> 32)
 154		funcname[i+4] = byte(v >> 24)
 155		funcname[i+5] = byte(v >> 16)
 156		funcname[i+6] = byte(v >> 8)
 157		funcname[i+7] = byte(v)
 158	}
 159
 160	runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l
 161		[]uintptr{uintptr(unsafe.Pointer(&funcname[0])), nameLen})
 162
 163	name := string(funcname[:nameLen])
 164	if name != funcName {
 165		return 1
 166	}
 167
 168	return 0
 169}
 170
 171// For detection of capabilities on a system.
 172// Is function descriptor f a valid function?
 173func isValidLeFunc(f uintptr) error {
 174	ret := funcptrtest(f, "")
 175	if ret != 0 {
 176		return fmt.Errorf("Bad pointer, not an LE function ")
 177	}
 178	return nil
 179}
 180
 181// Retrieve function name from descriptor
 182func getLeFuncName(f uintptr) (string, error) {
 183	// assume it has been checked, only check ppa1 validity here
 184	entry := ((*[2]uintptr)(unsafe.Pointer(f)))[1]
 185	preamp := ((*[4]uint32)(unsafe.Pointer(entry - eyecatcherOffset)))
 186
 187	offsetPpa1 := preamp[2]
 188	if offsetPpa1 > 0x0ffff {
 189		return "", fmt.Errorf("PPA1 offset seems too big 0x%x\n", offsetPpa1)
 190	}
 191
 192	ppa1 := uintptr(unsafe.Pointer(preamp)) + uintptr(offsetPpa1)
 193	res := ptrtest(ppa1)
 194	if res != 0 {
 195		return "", fmt.Errorf("PPA1 address not valid")
 196	}
 197
 198	size := *(*uint16)(unsafe.Pointer(ppa1 + nameLenOffset))
 199	if size > 128 {
 200		return "", fmt.Errorf("Function name seems too long, length=%d\n", size)
 201	}
 202
 203	var name [128]byte
 204	funcname := (*[128]byte)(unsafe.Pointer(ppa1 + nameOffset))
 205	copy(name[0:size], funcname[0:size])
 206
 207	runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l
 208		[]uintptr{uintptr(unsafe.Pointer(&name[0])), uintptr(size)})
 209
 210	return string(name[:size]), nil
 211}
 212
 213// Check z/OS version
 214func zosLeVersion() (version, release uint32) {
 215	p1 := (*(*uintptr)(unsafe.Pointer(uintptr(1208)))) >> 32
 216	p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 88)))
 217	p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 8)))
 218	p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 984)))
 219	vrm := *(*uint32)(unsafe.Pointer(p1 + 80))
 220	version = (vrm & 0x00ff0000) >> 16
 221	release = (vrm & 0x0000ff00) >> 8
 222	return
 223}
 224
 225// returns a zos C FILE * for stdio fd 0, 1, 2
 226func ZosStdioFilep(fd int32) uintptr {
 227	return uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(uint64(*(*uint32)(unsafe.Pointer(uintptr(1208)))) + 80))) + uint64((fd+2)<<3))))))))
 228}
 229
 230func copyStat(stat *Stat_t, statLE *Stat_LE_t) {
 231	stat.Dev = uint64(statLE.Dev)
 232	stat.Ino = uint64(statLE.Ino)
 233	stat.Nlink = uint64(statLE.Nlink)
 234	stat.Mode = uint32(statLE.Mode)
 235	stat.Uid = uint32(statLE.Uid)
 236	stat.Gid = uint32(statLE.Gid)
 237	stat.Rdev = uint64(statLE.Rdev)
 238	stat.Size = statLE.Size
 239	stat.Atim.Sec = int64(statLE.Atim)
 240	stat.Atim.Nsec = 0 //zos doesn't return nanoseconds
 241	stat.Mtim.Sec = int64(statLE.Mtim)
 242	stat.Mtim.Nsec = 0 //zos doesn't return nanoseconds
 243	stat.Ctim.Sec = int64(statLE.Ctim)
 244	stat.Ctim.Nsec = 0 //zos doesn't return nanoseconds
 245	stat.Blksize = int64(statLE.Blksize)
 246	stat.Blocks = statLE.Blocks
 247}
 248
 249func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
 250func svcLoad(name *byte) unsafe.Pointer
 251func svcUnload(name *byte, fnptr unsafe.Pointer) int64
 252
 253func (d *Dirent) NameString() string {
 254	if d == nil {
 255		return ""
 256	}
 257	s := string(d.Name[:])
 258	idx := strings.IndexByte(s, 0)
 259	if idx == -1 {
 260		return s
 261	} else {
 262		return s[:idx]
 263	}
 264}
 265
 266func DecodeData(dest []byte, sz int, val uint64) {
 267	for i := 0; i < sz; i++ {
 268		dest[sz-1-i] = byte((val >> (uint64(i * 8))) & 0xff)
 269	}
 270}
 271
 272func EncodeData(data []byte) uint64 {
 273	var value uint64
 274	sz := len(data)
 275	for i := 0; i < sz; i++ {
 276		value |= uint64(data[i]) << uint64(((sz - i - 1) * 8))
 277	}
 278	return value
 279}
 280
 281func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
 282	if sa.Port < 0 || sa.Port > 0xFFFF {
 283		return nil, 0, EINVAL
 284	}
 285	sa.raw.Len = SizeofSockaddrInet4
 286	sa.raw.Family = AF_INET
 287	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
 288	p[0] = byte(sa.Port >> 8)
 289	p[1] = byte(sa.Port)
 290	for i := 0; i < len(sa.Addr); i++ {
 291		sa.raw.Addr[i] = sa.Addr[i]
 292	}
 293	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
 294}
 295
 296func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
 297	if sa.Port < 0 || sa.Port > 0xFFFF {
 298		return nil, 0, EINVAL
 299	}
 300	sa.raw.Len = SizeofSockaddrInet6
 301	sa.raw.Family = AF_INET6
 302	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
 303	p[0] = byte(sa.Port >> 8)
 304	p[1] = byte(sa.Port)
 305	sa.raw.Scope_id = sa.ZoneId
 306	for i := 0; i < len(sa.Addr); i++ {
 307		sa.raw.Addr[i] = sa.Addr[i]
 308	}
 309	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
 310}
 311
 312func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
 313	name := sa.Name
 314	n := len(name)
 315	if n >= len(sa.raw.Path) || n == 0 {
 316		return nil, 0, EINVAL
 317	}
 318	sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
 319	sa.raw.Family = AF_UNIX
 320	for i := 0; i < n; i++ {
 321		sa.raw.Path[i] = int8(name[i])
 322	}
 323	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
 324}
 325
 326func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) {
 327	// TODO(neeilan): Implement use of first param (fd)
 328	switch rsa.Addr.Family {
 329	case AF_UNIX:
 330		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
 331		sa := new(SockaddrUnix)
 332		// For z/OS, only replace NUL with @ when the
 333		// length is not zero.
 334		if pp.Len != 0 && pp.Path[0] == 0 {
 335			// "Abstract" Unix domain socket.
 336			// Rewrite leading NUL as @ for textual display.
 337			// (This is the standard convention.)
 338			// Not friendly to overwrite in place,
 339			// but the callers below don't care.
 340			pp.Path[0] = '@'
 341		}
 342
 343		// Assume path ends at NUL.
 344		//
 345		// For z/OS, the length of the name is a field
 346		// in the structure. To be on the safe side, we
 347		// will still scan the name for a NUL but only
 348		// to the length provided in the structure.
 349		//
 350		// This is not technically the Linux semantics for
 351		// abstract Unix domain sockets--they are supposed
 352		// to be uninterpreted fixed-size binary blobs--but
 353		// everyone uses this convention.
 354		n := 0
 355		for n < int(pp.Len) && pp.Path[n] != 0 {
 356			n++
 357		}
 358		sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
 359		return sa, nil
 360
 361	case AF_INET:
 362		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
 363		sa := new(SockaddrInet4)
 364		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
 365		sa.Port = int(p[0])<<8 + int(p[1])
 366		for i := 0; i < len(sa.Addr); i++ {
 367			sa.Addr[i] = pp.Addr[i]
 368		}
 369		return sa, nil
 370
 371	case AF_INET6:
 372		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
 373		sa := new(SockaddrInet6)
 374		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
 375		sa.Port = int(p[0])<<8 + int(p[1])
 376		sa.ZoneId = pp.Scope_id
 377		for i := 0; i < len(sa.Addr); i++ {
 378			sa.Addr[i] = pp.Addr[i]
 379		}
 380		return sa, nil
 381	}
 382	return nil, EAFNOSUPPORT
 383}
 384
 385func Accept(fd int) (nfd int, sa Sockaddr, err error) {
 386	var rsa RawSockaddrAny
 387	var len _Socklen = SizeofSockaddrAny
 388	nfd, err = accept(fd, &rsa, &len)
 389	if err != nil {
 390		return
 391	}
 392	// TODO(neeilan): Remove 0 in call
 393	sa, err = anyToSockaddr(0, &rsa)
 394	if err != nil {
 395		Close(nfd)
 396		nfd = 0
 397	}
 398	return
 399}
 400
 401func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {
 402	var rsa RawSockaddrAny
 403	var len _Socklen = SizeofSockaddrAny
 404	nfd, err = accept4(fd, &rsa, &len, flags)
 405	if err != nil {
 406		return
 407	}
 408	if len > SizeofSockaddrAny {
 409		panic("RawSockaddrAny too small")
 410	}
 411	// TODO(neeilan): Remove 0 in call
 412	sa, err = anyToSockaddr(0, &rsa)
 413	if err != nil {
 414		Close(nfd)
 415		nfd = 0
 416	}
 417	return
 418}
 419
 420func Ctermid() (tty string, err error) {
 421	var termdev [1025]byte
 422	runtime.EnterSyscall()
 423	r0, err2, err1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___CTERMID_A<<4, uintptr(unsafe.Pointer(&termdev[0])))
 424	runtime.ExitSyscall()
 425	if r0 == 0 {
 426		return "", fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2)
 427	}
 428	s := string(termdev[:])
 429	idx := strings.Index(s, string(rune(0)))
 430	if idx == -1 {
 431		tty = s
 432	} else {
 433		tty = s[:idx]
 434	}
 435	return
 436}
 437
 438func (iov *Iovec) SetLen(length int) {
 439	iov.Len = uint64(length)
 440}
 441
 442func (msghdr *Msghdr) SetControllen(length int) {
 443	msghdr.Controllen = int32(length)
 444}
 445
 446func (cmsg *Cmsghdr) SetLen(length int) {
 447	cmsg.Len = int32(length)
 448}
 449
 450//sys   fcntl(fd int, cmd int, arg int) (val int, err error)
 451//sys   Flistxattr(fd int, dest []byte) (sz int, err error) = SYS___FLISTXATTR_A
 452//sys   Fremovexattr(fd int, attr string) (err error) = SYS___FREMOVEXATTR_A
 453//sys	read(fd int, p []byte) (n int, err error)
 454//sys	write(fd int, p []byte) (n int, err error)
 455
 456//sys   Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) = SYS___FGETXATTR_A
 457//sys   Fsetxattr(fd int, attr string, data []byte, flag int) (err error) = SYS___FSETXATTR_A
 458
 459//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = SYS___ACCEPT_A
 460//sys	accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = SYS___ACCEPT4_A
 461//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___BIND_A
 462//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___CONNECT_A
 463//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
 464//sysnb	setgroups(n int, list *_Gid_t) (err error)
 465//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
 466//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
 467//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
 468//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
 469//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETPEERNAME_A
 470//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETSOCKNAME_A
 471//sys   Removexattr(path string, attr string) (err error) = SYS___REMOVEXATTR_A
 472//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = SYS___RECVFROM_A
 473//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = SYS___SENDTO_A
 474//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___RECVMSG_A
 475//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___SENDMSG_A
 476//sys   mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) = SYS_MMAP
 477//sys   munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP
 478//sys   ioctl(fd int, req int, arg uintptr) (err error) = SYS_IOCTL
 479//sys   ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = SYS_IOCTL
 480//sys	shmat(id int, addr uintptr, flag int) (ret uintptr, err error) = SYS_SHMAT
 481//sys	shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) = SYS_SHMCTL64
 482//sys	shmdt(addr uintptr) (err error) = SYS_SHMDT
 483//sys	shmget(key int, size int, flag int) (id int, err error) = SYS_SHMGET
 484
 485//sys   Access(path string, mode uint32) (err error) = SYS___ACCESS_A
 486//sys   Chdir(path string) (err error) = SYS___CHDIR_A
 487//sys	Chown(path string, uid int, gid int) (err error) = SYS___CHOWN_A
 488//sys	Chmod(path string, mode uint32) (err error) = SYS___CHMOD_A
 489//sys   Creat(path string, mode uint32) (fd int, err error) = SYS___CREAT_A
 490//sys	Dup(oldfd int) (fd int, err error)
 491//sys	Dup2(oldfd int, newfd int) (err error)
 492//sys	Dup3(oldfd int, newfd int, flags int) (err error) = SYS_DUP3
 493//sys	Dirfd(dirp uintptr) (fd int, err error) = SYS_DIRFD
 494//sys	EpollCreate(size int) (fd int, err error) = SYS_EPOLL_CREATE
 495//sys	EpollCreate1(flags int) (fd int, err error) = SYS_EPOLL_CREATE1
 496//sys	EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) = SYS_EPOLL_CTL
 497//sys	EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) = SYS_EPOLL_PWAIT
 498//sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_WAIT
 499//sys	Errno2() (er2 int) = SYS___ERRNO2
 500//sys	Eventfd(initval uint, flags int) (fd int, err error) = SYS_EVENTFD
 501//sys	Exit(code int)
 502//sys	Faccessat(dirfd int, path string, mode uint32, flags int) (err error) = SYS___FACCESSAT_A
 503
 504func Faccessat2(dirfd int, path string, mode uint32, flags int) (err error) {
 505	return Faccessat(dirfd, path, mode, flags)
 506}
 507
 508//sys	Fchdir(fd int) (err error)
 509//sys	Fchmod(fd int, mode uint32) (err error)
 510//sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) = SYS___FCHMODAT_A
 511//sys	Fchown(fd int, uid int, gid int) (err error)
 512//sys	Fchownat(fd int, path string, uid int, gid int, flags int) (err error) = SYS___FCHOWNAT_A
 513//sys	FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) = SYS_FCNTL
 514//sys	Fdatasync(fd int) (err error) = SYS_FDATASYNC
 515//sys	fstat(fd int, stat *Stat_LE_t) (err error)
 516//sys	fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) = SYS___FSTATAT_A
 517
 518func Fstat(fd int, stat *Stat_t) (err error) {
 519	var statLE Stat_LE_t
 520	err = fstat(fd, &statLE)
 521	copyStat(stat, &statLE)
 522	return
 523}
 524
 525func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
 526	var statLE Stat_LE_t
 527	err = fstatat(dirfd, path, &statLE, flags)
 528	copyStat(stat, &statLE)
 529	return
 530}
 531
 532func impl_Getxattr(path string, attr string, dest []byte) (sz int, err error) {
 533	var _p0 *byte
 534	_p0, err = BytePtrFromString(path)
 535	if err != nil {
 536		return
 537	}
 538	var _p1 *byte
 539	_p1, err = BytePtrFromString(attr)
 540	if err != nil {
 541		return
 542	}
 543	var _p2 unsafe.Pointer
 544	if len(dest) > 0 {
 545		_p2 = unsafe.Pointer(&dest[0])
 546	} else {
 547		_p2 = unsafe.Pointer(&_zero)
 548	}
 549	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)))
 550	sz = int(r0)
 551	if int64(r0) == -1 {
 552		err = errnoErr2(e1, e2)
 553	}
 554	return
 555}
 556
 557//go:nosplit
 558func get_GetxattrAddr() *(func(path string, attr string, dest []byte) (sz int, err error))
 559
 560var Getxattr = enter_Getxattr
 561
 562func enter_Getxattr(path string, attr string, dest []byte) (sz int, err error) {
 563	funcref := get_GetxattrAddr()
 564	if validGetxattr() {
 565		*funcref = impl_Getxattr
 566	} else {
 567		*funcref = error_Getxattr
 568	}
 569	return (*funcref)(path, attr, dest)
 570}
 571
 572func error_Getxattr(path string, attr string, dest []byte) (sz int, err error) {
 573	return -1, ENOSYS
 574}
 575
 576func validGetxattr() bool {
 577	if funcptrtest(GetZosLibVec()+SYS___GETXATTR_A<<4, "") == 0 {
 578		if name, err := getLeFuncName(GetZosLibVec() + SYS___GETXATTR_A<<4); err == nil {
 579			return name == "__getxattr_a"
 580		}
 581	}
 582	return false
 583}
 584
 585//sys   Lgetxattr(link string, attr string, dest []byte) (sz int, err error) = SYS___LGETXATTR_A
 586//sys   Lsetxattr(path string, attr string, data []byte, flags int) (err error) = SYS___LSETXATTR_A
 587
 588func impl_Setxattr(path string, attr string, data []byte, flags int) (err error) {
 589	var _p0 *byte
 590	_p0, err = BytePtrFromString(path)
 591	if err != nil {
 592		return
 593	}
 594	var _p1 *byte
 595	_p1, err = BytePtrFromString(attr)
 596	if err != nil {
 597		return
 598	}
 599	var _p2 unsafe.Pointer
 600	if len(data) > 0 {
 601		_p2 = unsafe.Pointer(&data[0])
 602	} else {
 603		_p2 = unsafe.Pointer(&_zero)
 604	}
 605	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags))
 606	if int64(r0) == -1 {
 607		err = errnoErr2(e1, e2)
 608	}
 609	return
 610}
 611
 612//go:nosplit
 613func get_SetxattrAddr() *(func(path string, attr string, data []byte, flags int) (err error))
 614
 615var Setxattr = enter_Setxattr
 616
 617func enter_Setxattr(path string, attr string, data []byte, flags int) (err error) {
 618	funcref := get_SetxattrAddr()
 619	if validSetxattr() {
 620		*funcref = impl_Setxattr
 621	} else {
 622		*funcref = error_Setxattr
 623	}
 624	return (*funcref)(path, attr, data, flags)
 625}
 626
 627func error_Setxattr(path string, attr string, data []byte, flags int) (err error) {
 628	return ENOSYS
 629}
 630
 631func validSetxattr() bool {
 632	if funcptrtest(GetZosLibVec()+SYS___SETXATTR_A<<4, "") == 0 {
 633		if name, err := getLeFuncName(GetZosLibVec() + SYS___SETXATTR_A<<4); err == nil {
 634			return name == "__setxattr_a"
 635		}
 636	}
 637	return false
 638}
 639
 640//sys	Fstatfs(fd int, buf *Statfs_t) (err error) = SYS_FSTATFS
 641//sys	Fstatvfs(fd int, stat *Statvfs_t) (err error) = SYS_FSTATVFS
 642//sys	Fsync(fd int) (err error)
 643//sys	Futimes(fd int, tv []Timeval) (err error) = SYS_FUTIMES
 644//sys	Futimesat(dirfd int, path string, tv []Timeval) (err error) = SYS___FUTIMESAT_A
 645//sys	Ftruncate(fd int, length int64) (err error)
 646//sys	Getrandom(buf []byte, flags int) (n int, err error) = SYS_GETRANDOM
 647//sys	InotifyInit() (fd int, err error) = SYS_INOTIFY_INIT
 648//sys	InotifyInit1(flags int) (fd int, err error) = SYS_INOTIFY_INIT1
 649//sys	InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) = SYS___INOTIFY_ADD_WATCH_A
 650//sys	InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) = SYS_INOTIFY_RM_WATCH
 651//sys   Listxattr(path string, dest []byte) (sz int, err error) = SYS___LISTXATTR_A
 652//sys   Llistxattr(path string, dest []byte) (sz int, err error) = SYS___LLISTXATTR_A
 653//sys   Lremovexattr(path string, attr string) (err error) = SYS___LREMOVEXATTR_A
 654//sys	Lutimes(path string, tv []Timeval) (err error) = SYS___LUTIMES_A
 655//sys   Mprotect(b []byte, prot int) (err error) = SYS_MPROTECT
 656//sys   Msync(b []byte, flags int) (err error) = SYS_MSYNC
 657//sys   Console2(cmsg *ConsMsg2, modstr *byte, concmd *uint32) (err error) = SYS___CONSOLE2
 658
 659// Pipe2 begin
 660
 661//go:nosplit
 662func getPipe2Addr() *(func([]int, int) error)
 663
 664var Pipe2 = pipe2Enter
 665
 666func pipe2Enter(p []int, flags int) (err error) {
 667	if funcptrtest(GetZosLibVec()+SYS_PIPE2<<4, "") == 0 {
 668		*getPipe2Addr() = pipe2Impl
 669	} else {
 670		*getPipe2Addr() = pipe2Error
 671	}
 672	return (*getPipe2Addr())(p, flags)
 673}
 674
 675func pipe2Impl(p []int, flags int) (err error) {
 676	var pp [2]_C_int
 677	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PIPE2<<4, uintptr(unsafe.Pointer(&pp[0])), uintptr(flags))
 678	if int64(r0) == -1 {
 679		err = errnoErr2(e1, e2)
 680	} else {
 681		p[0] = int(pp[0])
 682		p[1] = int(pp[1])
 683	}
 684	return
 685}
 686func pipe2Error(p []int, flags int) (err error) {
 687	return fmt.Errorf("Pipe2 is not available on this system")
 688}
 689
 690// Pipe2 end
 691
 692//sys   Poll(fds []PollFd, timeout int) (n int, err error) = SYS_POLL
 693
 694func Readdir(dir uintptr) (dirent *Dirent, err error) {
 695	runtime.EnterSyscall()
 696	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READDIR_A<<4, uintptr(dir))
 697	runtime.ExitSyscall()
 698	dirent = (*Dirent)(unsafe.Pointer(r0))
 699	if int64(r0) == -1 {
 700		err = errnoErr2(e1, e2)
 701	}
 702	return
 703}
 704
 705//sys	Readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) = SYS___READDIR_R_A
 706//sys	Statfs(path string, buf *Statfs_t) (err error) = SYS___STATFS_A
 707//sys	Syncfs(fd int) (err error) = SYS_SYNCFS
 708//sys   Times(tms *Tms) (ticks uintptr, err error) = SYS_TIMES
 709//sys   W_Getmntent(buff *byte, size int) (lastsys int, err error) = SYS_W_GETMNTENT
 710//sys   W_Getmntent_A(buff *byte, size int) (lastsys int, err error) = SYS___W_GETMNTENT_A
 711
 712//sys   mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) = SYS___MOUNT_A
 713//sys   unmount_LE(filesystem string, mtm int) (err error) = SYS___UMOUNT_A
 714//sys   Chroot(path string) (err error) = SYS___CHROOT_A
 715//sys   Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) = SYS_SELECT
 716//sysnb Uname(buf *Utsname) (err error) = SYS_____OSNAME_A
 717//sys   Unshare(flags int) (err error) = SYS_UNSHARE
 718
 719func Ptsname(fd int) (name string, err error) {
 720	runtime.EnterSyscall()
 721	r0, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___PTSNAME_A<<4, uintptr(fd))
 722	runtime.ExitSyscall()
 723	if r0 == 0 {
 724		err = errnoErr2(e1, e2)
 725	} else {
 726		name = u2s(unsafe.Pointer(r0))
 727	}
 728	return
 729}
 730
 731func u2s(cstr unsafe.Pointer) string {
 732	str := (*[1024]uint8)(cstr)
 733	i := 0
 734	for str[i] != 0 {
 735		i++
 736	}
 737	return string(str[:i])
 738}
 739
 740func Close(fd int) (err error) {
 741	runtime.EnterSyscall()
 742	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSE<<4, uintptr(fd))
 743	runtime.ExitSyscall()
 744	for i := 0; e1 == EAGAIN && i < 10; i++ {
 745		runtime.EnterSyscall()
 746		CallLeFuncWithErr(GetZosLibVec()+SYS_USLEEP<<4, uintptr(10))
 747		runtime.ExitSyscall()
 748		runtime.EnterSyscall()
 749		r0, e2, e1 = CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSE<<4, uintptr(fd))
 750		runtime.ExitSyscall()
 751	}
 752	if r0 != 0 {
 753		err = errnoErr2(e1, e2)
 754	}
 755	return
 756}
 757
 758// Dummy function: there are no semantics for Madvise on z/OS
 759func Madvise(b []byte, advice int) (err error) {
 760	return
 761}
 762
 763func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
 764	return mapper.Mmap(fd, offset, length, prot, flags)
 765}
 766
 767func Munmap(b []byte) (err error) {
 768	return mapper.Munmap(b)
 769}
 770
 771func MmapPtr(fd int, offset int64, addr unsafe.Pointer, length uintptr, prot int, flags int) (ret unsafe.Pointer, err error) {
 772	xaddr, err := mapper.mmap(uintptr(addr), length, prot, flags, fd, offset)
 773	return unsafe.Pointer(xaddr), err
 774}
 775
 776func MunmapPtr(addr unsafe.Pointer, length uintptr) (err error) {
 777	return mapper.munmap(uintptr(addr), length)
 778}
 779
 780//sys   Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A
 781//sysnb	Getgid() (gid int)
 782//sysnb	Getpid() (pid int)
 783//sysnb	Getpgid(pid int) (pgid int, err error) = SYS_GETPGID
 784
 785func Getpgrp() (pid int) {
 786	pid, _ = Getpgid(0)
 787	return
 788}
 789
 790//sysnb	Getppid() (pid int)
 791//sys	Getpriority(which int, who int) (prio int, err error)
 792//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_GETRLIMIT
 793
 794//sysnb getrusage(who int, rusage *rusage_zos) (err error) = SYS_GETRUSAGE
 795
 796func Getrusage(who int, rusage *Rusage) (err error) {
 797	var ruz rusage_zos
 798	err = getrusage(who, &ruz)
 799	//Only the first two fields of Rusage are set
 800	rusage.Utime.Sec = ruz.Utime.Sec
 801	rusage.Utime.Usec = int64(ruz.Utime.Usec)
 802	rusage.Stime.Sec = ruz.Stime.Sec
 803	rusage.Stime.Usec = int64(ruz.Stime.Usec)
 804	return
 805}
 806
 807//sys	Getegid() (egid int) = SYS_GETEGID
 808//sys	Geteuid() (euid int) = SYS_GETEUID
 809//sysnb Getsid(pid int) (sid int, err error) = SYS_GETSID
 810//sysnb	Getuid() (uid int)
 811//sysnb	Kill(pid int, sig Signal) (err error)
 812//sys	Lchown(path string, uid int, gid int) (err error) = SYS___LCHOWN_A
 813//sys	Link(path string, link string) (err error) = SYS___LINK_A
 814//sys	Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) = SYS___LINKAT_A
 815//sys	Listen(s int, n int) (err error)
 816//sys	lstat(path string, stat *Stat_LE_t) (err error) = SYS___LSTAT_A
 817
 818func Lstat(path string, stat *Stat_t) (err error) {
 819	var statLE Stat_LE_t
 820	err = lstat(path, &statLE)
 821	copyStat(stat, &statLE)
 822	return
 823}
 824
 825// for checking symlinks begins with $VERSION/ $SYSNAME/ $SYSSYMR/ $SYSSYMA/
 826func isSpecialPath(path []byte) (v bool) {
 827	var special = [4][8]byte{
 828		{'V', 'E', 'R', 'S', 'I', 'O', 'N', '/'},
 829		{'S', 'Y', 'S', 'N', 'A', 'M', 'E', '/'},
 830		{'S', 'Y', 'S', 'S', 'Y', 'M', 'R', '/'},
 831		{'S', 'Y', 'S', 'S', 'Y', 'M', 'A', '/'}}
 832
 833	var i, j int
 834	for i = 0; i < len(special); i++ {
 835		for j = 0; j < len(special[i]); j++ {
 836			if path[j] != special[i][j] {
 837				break
 838			}
 839		}
 840		if j == len(special[i]) {
 841			return true
 842		}
 843	}
 844	return false
 845}
 846
 847func realpath(srcpath string, abspath []byte) (pathlen int, errno int) {
 848	var source [1024]byte
 849	copy(source[:], srcpath)
 850	source[len(srcpath)] = 0
 851	ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___REALPATH_A<<4, //__realpath_a()
 852		[]uintptr{uintptr(unsafe.Pointer(&source[0])),
 853			uintptr(unsafe.Pointer(&abspath[0]))})
 854	if ret != 0 {
 855		index := bytes.IndexByte(abspath[:], byte(0))
 856		if index != -1 {
 857			return index, 0
 858		}
 859	} else {
 860		errptr := (*int)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{}))) //__errno()
 861		return 0, *errptr
 862	}
 863	return 0, 245 // EBADDATA   245
 864}
 865
 866func Readlink(path string, buf []byte) (n int, err error) {
 867	var _p0 *byte
 868	_p0, err = BytePtrFromString(path)
 869	if err != nil {
 870		return
 871	}
 872	var _p1 unsafe.Pointer
 873	if len(buf) > 0 {
 874		_p1 = unsafe.Pointer(&buf[0])
 875	} else {
 876		_p1 = unsafe.Pointer(&_zero)
 877	}
 878	n = int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___READLINK_A<<4,
 879		[]uintptr{uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))}))
 880	runtime.KeepAlive(unsafe.Pointer(_p0))
 881	if n == -1 {
 882		value := *(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{})))
 883		err = errnoErr(Errno(value))
 884	} else {
 885		if buf[0] == '$' {
 886			if isSpecialPath(buf[1:9]) {
 887				cnt, err1 := realpath(path, buf)
 888				if err1 == 0 {
 889					n = cnt
 890				}
 891			}
 892		}
 893	}
 894	return
 895}
 896
 897func impl_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
 898	var _p0 *byte
 899	_p0, err = BytePtrFromString(path)
 900	if err != nil {
 901		return
 902	}
 903	var _p1 unsafe.Pointer
 904	if len(buf) > 0 {
 905		_p1 = unsafe.Pointer(&buf[0])
 906	} else {
 907		_p1 = unsafe.Pointer(&_zero)
 908	}
 909	runtime.EnterSyscall()
 910	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READLINKAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 911	runtime.ExitSyscall()
 912	n = int(r0)
 913	if int64(r0) == -1 {
 914		err = errnoErr2(e1, e2)
 915		return n, err
 916	} else {
 917		if buf[0] == '$' {
 918			if isSpecialPath(buf[1:9]) {
 919				cnt, err1 := realpath(path, buf)
 920				if err1 == 0 {
 921					n = cnt
 922				}
 923			}
 924		}
 925	}
 926	return
 927}
 928
 929//go:nosplit
 930func get_ReadlinkatAddr() *(func(dirfd int, path string, buf []byte) (n int, err error))
 931
 932var Readlinkat = enter_Readlinkat
 933
 934func enter_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
 935	funcref := get_ReadlinkatAddr()
 936	if funcptrtest(GetZosLibVec()+SYS___READLINKAT_A<<4, "") == 0 {
 937		*funcref = impl_Readlinkat
 938	} else {
 939		*funcref = error_Readlinkat
 940	}
 941	return (*funcref)(dirfd, path, buf)
 942}
 943
 944func error_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
 945	n = -1
 946	err = ENOSYS
 947	return
 948}
 949
 950//sys	Mkdir(path string, mode uint32) (err error) = SYS___MKDIR_A
 951//sys	Mkdirat(dirfd int, path string, mode uint32) (err error) = SYS___MKDIRAT_A
 952//sys   Mkfifo(path string, mode uint32) (err error) = SYS___MKFIFO_A
 953//sys	Mknod(path string, mode uint32, dev int) (err error) = SYS___MKNOD_A
 954//sys	Mknodat(dirfd int, path string, mode uint32, dev int) (err error) = SYS___MKNODAT_A
 955//sys	PivotRoot(newroot string, oldroot string) (err error) = SYS___PIVOT_ROOT_A
 956//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
 957//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
 958//sys	Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) = SYS___PRCTL_A
 959//sysnb	Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT
 960//sys	Rename(from string, to string) (err error) = SYS___RENAME_A
 961//sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) = SYS___RENAMEAT_A
 962//sys	Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) = SYS___RENAMEAT2_A
 963//sys	Rmdir(path string) (err error) = SYS___RMDIR_A
 964//sys   Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
 965//sys	Setegid(egid int) (err error) = SYS_SETEGID
 966//sys	Seteuid(euid int) (err error) = SYS_SETEUID
 967//sys	Sethostname(p []byte) (err error) = SYS___SETHOSTNAME_A
 968//sys   Setns(fd int, nstype int) (err error) = SYS_SETNS
 969//sys	Setpriority(which int, who int, prio int) (err error)
 970//sysnb	Setpgid(pid int, pgid int) (err error) = SYS_SETPGID
 971//sysnb	Setrlimit(resource int, lim *Rlimit) (err error)
 972//sysnb	Setregid(rgid int, egid int) (err error) = SYS_SETREGID
 973//sysnb	Setreuid(ruid int, euid int) (err error) = SYS_SETREUID
 974//sysnb	Setsid() (pid int, err error) = SYS_SETSID
 975//sys	Setuid(uid int) (err error) = SYS_SETUID
 976//sys	Setgid(uid int) (err error) = SYS_SETGID
 977//sys	Shutdown(fd int, how int) (err error)
 978//sys	stat(path string, statLE *Stat_LE_t) (err error) = SYS___STAT_A
 979
 980func Stat(path string, sta *Stat_t) (err error) {
 981	var statLE Stat_LE_t
 982	err = stat(path, &statLE)
 983	copyStat(sta, &statLE)
 984	return
 985}
 986
 987//sys	Symlink(path string, link string) (err error) = SYS___SYMLINK_A
 988//sys	Symlinkat(oldPath string, dirfd int, newPath string) (err error) = SYS___SYMLINKAT_A
 989//sys	Sync() = SYS_SYNC
 990//sys	Truncate(path string, length int64) (err error) = SYS___TRUNCATE_A
 991//sys	Tcgetattr(fildes int, termptr *Termios) (err error) = SYS_TCGETATTR
 992//sys	Tcsetattr(fildes int, when int, termptr *Termios) (err error) = SYS_TCSETATTR
 993//sys	Umask(mask int) (oldmask int)
 994//sys	Unlink(path string) (err error) = SYS___UNLINK_A
 995//sys	Unlinkat(dirfd int, path string, flags int) (err error) = SYS___UNLINKAT_A
 996//sys	Utime(path string, utim *Utimbuf) (err error) = SYS___UTIME_A
 997
 998//sys	open(path string, mode int, perm uint32) (fd int, err error) = SYS___OPEN_A
 999
1000func Open(path string, mode int, perm uint32) (fd int, err error) {
1001	if mode&O_ACCMODE == 0 {
1002		mode |= O_RDONLY
1003	}
1004	return open(path, mode, perm)
1005}
1006
1007//sys	openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) = SYS___OPENAT_A
1008
1009func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
1010	if flags&O_ACCMODE == 0 {
1011		flags |= O_RDONLY
1012	}
1013	return openat(dirfd, path, flags, mode)
1014}
1015
1016//sys	openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) = SYS___OPENAT2_A
1017
1018func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) {
1019	if how.Flags&O_ACCMODE == 0 {
1020		how.Flags |= O_RDONLY
1021	}
1022	return openat2(dirfd, path, how, SizeofOpenHow)
1023}
1024
1025func ZosFdToPath(dirfd int) (path string, err error) {
1026	var buffer [1024]byte
1027	runtime.EnterSyscall()
1028	ret, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_W_IOCTL<<4, uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0])))
1029	runtime.ExitSyscall()
1030	if ret == 0 {
1031		zb := bytes.IndexByte(buffer[:], 0)
1032		if zb == -1 {
1033			zb = len(buffer)
1034		}
1035		CallLeFuncWithErr(GetZosLibVec()+SYS___E2A_L<<4, uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb))
1036		return string(buffer[:zb]), nil
1037	}
1038	return "", errnoErr2(e1, e2)
1039}
1040
1041//sys	remove(path string) (err error)
1042
1043func Remove(path string) error {
1044	return remove(path)
1045}
1046
1047const ImplementsGetwd = true
1048
1049func Getcwd(buf []byte) (n int, err error) {
1050	var p unsafe.Pointer
1051	if len(buf) > 0 {
1052		p = unsafe.Pointer(&buf[0])
1053	} else {
1054		p = unsafe.Pointer(&_zero)
1055	}
1056	runtime.EnterSyscall()
1057	r0, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___GETCWD_A<<4, uintptr(p), uintptr(len(buf)))
1058	runtime.ExitSyscall()
1059	n = clen(buf) + 1
1060	if r0 == 0 {
1061		err = errnoErr2(e1, e2)
1062	}
1063	return
1064}
1065
1066func Getwd() (wd string, err error) {
1067	var buf [PathMax]byte
1068	n, err := Getcwd(buf[0:])
1069	if err != nil {
1070		return "", err
1071	}
1072	// Getcwd returns the number of bytes written to buf, including the NUL.
1073	if n < 1 || n > len(buf) || buf[n-1] != 0 {
1074		return "", EINVAL
1075	}
1076	return string(buf[0 : n-1]), nil
1077}
1078
1079func Getgroups() (gids []int, err error) {
1080	n, err := getgroups(0, nil)
1081	if err != nil {
1082		return nil, err
1083	}
1084	if n == 0 {
1085		return nil, nil
1086	}
1087
1088	// Sanity check group count.  Max is 1<<16 on Linux.
1089	if n < 0 || n > 1<<20 {
1090		return nil, EINVAL
1091	}
1092
1093	a := make([]_Gid_t, n)
1094	n, err = getgroups(n, &a[0])
1095	if err != nil {
1096		return nil, err
1097	}
1098	gids = make([]int, n)
1099	for i, v := range a[0:n] {
1100		gids[i] = int(v)
1101	}
1102	return
1103}
1104
1105func Setgroups(gids []int) (err error) {
1106	if len(gids) == 0 {
1107		return setgroups(0, nil)
1108	}
1109
1110	a := make([]_Gid_t, len(gids))
1111	for i, v := range gids {
1112		a[i] = _Gid_t(v)
1113	}
1114	return setgroups(len(a), &a[0])
1115}
1116
1117func gettid() uint64
1118
1119func Gettid() (tid int) {
1120	return int(gettid())
1121}
1122
1123type WaitStatus uint32
1124
1125// Wait status is 7 bits at bottom, either 0 (exited),
1126// 0x7F (stopped), or a signal number that caused an exit.
1127// The 0x80 bit is whether there was a core dump.
1128// An extra number (exit code, signal causing a stop)
1129// is in the high bits.  At least that's the idea.
1130// There are various irregularities.  For example, the
1131// "continued" status is 0xFFFF, distinguishing itself
1132// from stopped via the core dump bit.
1133
1134const (
1135	mask    = 0x7F
1136	core    = 0x80
1137	exited  = 0x00
1138	stopped = 0x7F
1139	shift   = 8
1140)
1141
1142func (w WaitStatus) Exited() bool { return w&mask == exited }
1143
1144func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited }
1145
1146func (w WaitStatus) Stopped() bool { return w&0xFF == stopped }
1147
1148func (w WaitStatus) Continued() bool { return w == 0xFFFF }
1149
1150func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
1151
1152func (w WaitStatus) ExitStatus() int {
1153	if !w.Exited() {
1154		return -1
1155	}
1156	return int(w>>shift) & 0xFF
1157}
1158
1159func (w WaitStatus) Signal() Signal {
1160	if !w.Signaled() {
1161		return -1
1162	}
1163	return Signal(w & mask)
1164}
1165
1166func (w WaitStatus) StopSignal() Signal {
1167	if !w.Stopped() {
1168		return -1
1169	}
1170	return Signal(w>>shift) & 0xFF
1171}
1172
1173func (w WaitStatus) TrapCause() int { return -1 }
1174
1175//sys	waitid(idType int, id int, info *Siginfo, options int) (err error)
1176
1177func Waitid(idType int, id int, info *Siginfo, options int, rusage *Rusage) (err error) {
1178	return waitid(idType, id, info, options)
1179}
1180
1181//sys	waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error)
1182
1183func impl_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
1184	runtime.EnterSyscall()
1185	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAIT4<<4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)))
1186	runtime.ExitSyscall()
1187	wpid = int(r0)
1188	if int64(r0) == -1 {
1189		err = errnoErr2(e1, e2)
1190	}
1191	return
1192}
1193
1194//go:nosplit
1195func get_Wait4Addr() *(func(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error))
1196
1197var Wait4 = enter_Wait4
1198
1199func enter_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
1200	funcref := get_Wait4Addr()
1201	if funcptrtest(GetZosLibVec()+SYS_WAIT4<<4, "") == 0 {
1202		*funcref = impl_Wait4
1203	} else {
1204		*funcref = legacyWait4
1205	}
1206	return (*funcref)(pid, wstatus, options, rusage)
1207}
1208
1209func legacyWait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
1210	// TODO(mundaym): z/OS doesn't have wait4. I don't think getrusage does what we want.
1211	// At the moment rusage will not be touched.
1212	var status _C_int
1213	wpid, err = waitpid(pid, &status, options)
1214	if wstatus != nil {
1215		*wstatus = WaitStatus(status)
1216	}
1217	return
1218}
1219
1220//sysnb	gettimeofday(tv *timeval_zos) (err error)
1221
1222func Gettimeofday(tv *Timeval) (err error) {
1223	var tvz timeval_zos
1224	err = gettimeofday(&tvz)
1225	tv.Sec = tvz.Sec
1226	tv.Usec = int64(tvz.Usec)
1227	return
1228}
1229
1230func Time(t *Time_t) (tt Time_t, err error) {
1231	var tv Timeval
1232	err = Gettimeofday(&tv)
1233	if err != nil {
1234		return 0, err
1235	}
1236	if t != nil {
1237		*t = Time_t(tv.Sec)
1238	}
1239	return Time_t(tv.Sec), nil
1240}
1241
1242func setTimespec(sec, nsec int64) Timespec {
1243	return Timespec{Sec: sec, Nsec: nsec}
1244}
1245
1246func setTimeval(sec, usec int64) Timeval { //fix
1247	return Timeval{Sec: sec, Usec: usec}
1248}
1249
1250//sysnb pipe(p *[2]_C_int) (err error)
1251
1252func Pipe(p []int) (err error) {
1253	if len(p) != 2 {
1254		return EINVAL
1255	}
1256	var pp [2]_C_int
1257	err = pipe(&pp)
1258	p[0] = int(pp[0])
1259	p[1] = int(pp[1])
1260	return
1261}
1262
1263//sys	utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A
1264
1265func Utimes(path string, tv []Timeval) (err error) {
1266	if tv == nil {
1267		return utimes(path, nil)
1268	}
1269	if len(tv) != 2 {
1270		return EINVAL
1271	}
1272	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
1273}
1274
1275//sys	utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) = SYS___UTIMENSAT_A
1276
1277func validUtimensat() bool {
1278	if funcptrtest(GetZosLibVec()+SYS___UTIMENSAT_A<<4, "") == 0 {
1279		if name, err := getLeFuncName(GetZosLibVec() + SYS___UTIMENSAT_A<<4); err == nil {
1280			return name == "__utimensat_a"
1281		}
1282	}
1283	return false
1284}
1285
1286// Begin UtimesNano
1287
1288//go:nosplit
1289func get_UtimesNanoAddr() *(func(path string, ts []Timespec) (err error))
1290
1291var UtimesNano = enter_UtimesNano
1292
1293func enter_UtimesNano(path string, ts []Timespec) (err error) {
1294	funcref := get_UtimesNanoAddr()
1295	if validUtimensat() {
1296		*funcref = utimesNanoImpl
1297	} else {
1298		*funcref = legacyUtimesNano
1299	}
1300	return (*funcref)(path, ts)
1301}
1302
1303func utimesNanoImpl(path string, ts []Timespec) (err error) {
1304	if ts == nil {
1305		return utimensat(AT_FDCWD, path, nil, 0)
1306	}
1307	if len(ts) != 2 {
1308		return EINVAL
1309	}
1310	return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
1311}
1312
1313func legacyUtimesNano(path string, ts []Timespec) (err error) {
1314	if len(ts) != 2 {
1315		return EINVAL
1316	}
1317	// Not as efficient as it could be because Timespec and
1318	// Timeval have different types in the different OSes
1319	tv := [2]Timeval{
1320		NsecToTimeval(TimespecToNsec(ts[0])),
1321		NsecToTimeval(TimespecToNsec(ts[1])),
1322	}
1323	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
1324}
1325
1326// End UtimesNano
1327
1328// Begin UtimesNanoAt
1329
1330//go:nosplit
1331func get_UtimesNanoAtAddr() *(func(dirfd int, path string, ts []Timespec, flags int) (err error))
1332
1333var UtimesNanoAt = enter_UtimesNanoAt
1334
1335func enter_UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) {
1336	funcref := get_UtimesNanoAtAddr()
1337	if validUtimensat() {
1338		*funcref = utimesNanoAtImpl
1339	} else {
1340		*funcref = legacyUtimesNanoAt
1341	}
1342	return (*funcref)(dirfd, path, ts, flags)
1343}
1344
1345func utimesNanoAtImpl(dirfd int, path string, ts []Timespec, flags int) (err error) {
1346	if ts == nil {
1347		return utimensat(dirfd, path, nil, flags)
1348	}
1349	if len(ts) != 2 {
1350		return EINVAL
1351	}
1352	return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
1353}
1354
1355func legacyUtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) {
1356	if path[0] != '/' {
1357		dirPath, err := ZosFdToPath(dirfd)
1358		if err != nil {
1359			return err
1360		}
1361		path = dirPath + "/" + path
1362	}
1363	if flags == AT_SYMLINK_NOFOLLOW {
1364		if len(ts) != 2 {
1365			return EINVAL
1366		}
1367
1368		if ts[0].Nsec >= 5e8 {
1369			ts[0].Sec++
1370		}
1371		ts[0].Nsec = 0
1372		if ts[1].Nsec >= 5e8 {
1373			ts[1].Sec++
1374		}
1375		ts[1].Nsec = 0
1376
1377		// Not as efficient as it could be because Timespec and
1378		// Timeval have different types in the different OSes
1379		tv := []Timeval{
1380			NsecToTimeval(TimespecToNsec(ts[0])),
1381			NsecToTimeval(TimespecToNsec(ts[1])),
1382		}
1383		return Lutimes(path, tv)
1384	}
1385	return UtimesNano(path, ts)
1386}
1387
1388// End UtimesNanoAt
1389
1390func Getsockname(fd int) (sa Sockaddr, err error) {
1391	var rsa RawSockaddrAny
1392	var len _Socklen = SizeofSockaddrAny
1393	if err = getsockname(fd, &rsa, &len); err != nil {
1394		return
1395	}
1396	// TODO(neeilan) : Remove this 0 ( added to get sys/unix compiling on z/OS )
1397	return anyToSockaddr(0, &rsa)
1398}
1399
1400const (
1401	// identifier constants
1402	nwmHeaderIdentifier    = 0xd5e6d4c8
1403	nwmFilterIdentifier    = 0xd5e6d4c6
1404	nwmTCPConnIdentifier   = 0xd5e6d4c3
1405	nwmRecHeaderIdentifier = 0xd5e6d4d9
1406	nwmIPStatsIdentifier   = 0xd5e6d4c9d7e2e340
1407	nwmIPGStatsIdentifier  = 0xd5e6d4c9d7c7e2e3
1408	nwmTCPStatsIdentifier  = 0xd5e6d4e3c3d7e2e3
1409	nwmUDPStatsIdentifier  = 0xd5e6d4e4c4d7e2e3
1410	nwmICMPGStatsEntry     = 0xd5e6d4c9c3d4d7c7
1411	nwmICMPTStatsEntry     = 0xd5e6d4c9c3d4d7e3
1412
1413	// nwmHeader constants
1414	nwmVersion1   = 1
1415	nwmVersion2   = 2
1416	nwmCurrentVer = 2
1417
1418	nwmTCPConnType     = 1
1419	nwmGlobalStatsType = 14
1420
1421	// nwmFilter constants
1422	nwmFilterLclAddrMask = 0x20000000 // Local address
1423	nwmFilterSrcAddrMask = 0x20000000 // Source address
1424	nwmFilterLclPortMask = 0x10000000 // Local port
1425	nwmFilterSrcPortMask = 0x10000000 // Source port
1426
1427	// nwmConnEntry constants
1428	nwmTCPStateClosed   = 1
1429	nwmTCPStateListen   = 2
1430	nwmTCPStateSynSent  = 3
1431	nwmTCPStateSynRcvd  = 4
1432	nwmTCPStateEstab    = 5
1433	nwmTCPStateFinWait1 = 6
1434	nwmTCPStateFinWait2 = 7
1435	nwmTCPStateClosWait = 8
1436	nwmTCPStateLastAck  = 9
1437	nwmTCPStateClosing  = 10
1438	nwmTCPStateTimeWait = 11
1439	nwmTCPStateDeletTCB = 12
1440
1441	// Existing constants on linux
1442	BPF_TCP_CLOSE        = 1
1443	BPF_TCP_LISTEN       = 2
1444	BPF_TCP_SYN_SENT     = 3
1445	BPF_TCP_SYN_RECV     = 4
1446	BPF_TCP_ESTABLISHED  = 5
1447	BPF_TCP_FIN_WAIT1    = 6
1448	BPF_TCP_FIN_WAIT2    = 7
1449	BPF_TCP_CLOSE_WAIT   = 8
1450	BPF_TCP_LAST_ACK     = 9
1451	BPF_TCP_CLOSING      = 10
1452	BPF_TCP_TIME_WAIT    = 11
1453	BPF_TCP_NEW_SYN_RECV = -1
1454	BPF_TCP_MAX_STATES   = -2
1455)
1456
1457type nwmTriplet struct {
1458	offset uint32
1459	length uint32
1460	number uint32
1461}
1462
1463type nwmQuadruplet struct {
1464	offset uint32
1465	length uint32
1466	number uint32
1467	match  uint32
1468}
1469
1470type nwmHeader struct {
1471	ident       uint32
1472	length      uint32
1473	version     uint16
1474	nwmType     uint16
1475	bytesNeeded uint32
1476	options     uint32
1477	_           [16]byte
1478	inputDesc   nwmTriplet
1479	outputDesc  nwmQuadruplet
1480}
1481
1482type nwmFilter struct {
1483	ident         uint32
1484	flags         uint32
1485	resourceName  [8]byte
1486	resourceId    uint32
1487	listenerId    uint32
1488	local         [28]byte // union of sockaddr4 and sockaddr6
1489	remote        [28]byte // union of sockaddr4 and sockaddr6
1490	_             uint16
1491	_             uint16
1492	asid          uint16
1493	_             [2]byte
1494	tnLuName      [8]byte
1495	tnMonGrp      uint32
1496	tnAppl        [8]byte
1497	applData      [40]byte
1498	nInterface    [16]byte
1499	dVipa         [16]byte
1500	dVipaPfx      uint16
1501	dVipaPort     uint16
1502	dVipaFamily   byte
1503	_             [3]byte
1504	destXCF       [16]byte
1505	destXCFPfx    uint16
1506	destXCFFamily byte
1507	_             [1]byte
1508	targIP        [16]byte
1509	targIPPfx     uint16
1510	targIPFamily  byte
1511	_             [1]byte
1512	_             [20]byte
1513}
1514
1515type nwmRecHeader struct {
1516	ident  uint32
1517	length uint32
1518	number byte
1519	_      [3]byte
1520}
1521
1522type nwmTCPStatsEntry struct {
1523	ident             uint64
1524	currEstab         uint32
1525	activeOpened      uint32
1526	passiveOpened     uint32
1527	connClosed        uint32
1528	estabResets       uint32
1529	attemptFails      uint32
1530	passiveDrops      uint32
1531	timeWaitReused    uint32
1532	inSegs            uint64
1533	predictAck        uint32
1534	predictData       uint32
1535	inDupAck          uint32
1536	inBadSum          uint32
1537	inBadLen          uint32
1538	inShort           uint32
1539	inDiscOldTime     uint32
1540	inAllBeforeWin    uint32
1541	inSomeBeforeWin   uint32
1542	inAllAfterWin     uint32
1543	inSomeAfterWin    uint32
1544	inOutOfOrder      uint32
1545	inAfterClose      uint32
1546	inWinProbes       uint32
1547	inWinUpdates      uint32
1548	outWinUpdates     uint32
1549	outSegs           uint64
1550	outDelayAcks      uint32
1551	outRsts           uint32
1552	retransSegs       uint32
1553	retransTimeouts   uint32
1554	retransDrops      uint32
1555	pmtuRetrans       uint32
1556	pmtuErrors        uint32
1557	outWinProbes      uint32
1558	probeDrops        uint32
1559	keepAliveProbes   uint32
1560	keepAliveDrops    uint32
1561	finwait2Drops     uint32
1562	acceptCount       uint64
1563	inBulkQSegs       uint64
1564	inDiscards        uint64
1565	connFloods        uint32
1566	connStalls        uint32
1567	cfgEphemDef       uint16
1568	ephemInUse        uint16
1569	ephemHiWater      uint16
1570	flags             byte
1571	_                 [1]byte
1572	ephemExhaust      uint32
1573	smcRCurrEstabLnks uint32
1574	smcRLnkActTimeOut uint32
1575	smcRActLnkOpened  uint32
1576	smcRPasLnkOpened  uint32
1577	smcRLnksClosed    uint32
1578	smcRCurrEstab     uint32
1579	smcRActiveOpened  uint32
1580	smcRPassiveOpened uint32
1581	smcRConnClosed    uint32
1582	smcRInSegs        uint64
1583	smcROutSegs       uint64
1584	smcRInRsts        uint32
1585	smcROutRsts       uint32
1586	smcDCurrEstabLnks uint32
1587	smcDActLnkOpened  uint32
1588	smcDPasLnkOpened  uint32
1589	smcDLnksClosed    uint32
1590	smcDCurrEstab     uint32
1591	smcDActiveOpened  uint32
1592	smcDPassiveOpened uint32
1593	smcDConnClosed    uint32
1594	smcDInSegs        uint64
1595	smcDOutSegs       uint64
1596	smcDInRsts        uint32
1597	smcDOutRsts       uint32
1598}
1599
1600type nwmConnEntry struct {
1601	ident             uint32
1602	local             [28]byte // union of sockaddr4 and sockaddr6
1603	remote            [28]byte // union of sockaddr4 and sockaddr6
1604	startTime         [8]byte  // uint64, changed to prevent padding from being inserted
1605	lastActivity      [8]byte  // uint64
1606	bytesIn           [8]byte  // uint64
1607	bytesOut          [8]byte  // uint64
1608	inSegs            [8]byte  // uint64
1609	outSegs           [8]byte  // uint64
1610	state             uint16
1611	activeOpen        byte
1612	flag01            byte
1613	outBuffered       uint32
1614	inBuffered        uint32
1615	maxSndWnd         uint32
1616	reXmtCount        uint32
1617	congestionWnd     uint32
1618	ssThresh          uint32
1619	roundTripTime     uint32
1620	roundTripVar      uint32
1621	sendMSS           uint32
1622	sndWnd            uint32
1623	rcvBufSize        uint32
1624	sndBufSize        uint32
1625	outOfOrderCount   uint32
1626	lcl0WindowCount   uint32
1627	rmt0WindowCount   uint32
1628	dupacks           uint32
1629	flag02            byte
1630	sockOpt6Cont      byte
1631	asid              uint16
1632	resourceName      [8]byte
1633	resourceId        uint32
1634	subtask           uint32
1635	sockOpt           byte
1636	sockOpt6          byte
1637	clusterConnFlag   byte
1638	proto             byte
1639	targetAppl        [8]byte
1640	luName            [8]byte
1641	clientUserId      [8]byte
1642	logMode           [8]byte
1643	timeStamp         uint32
1644	timeStampAge      uint32
1645	serverResourceId  uint32
1646	intfName          [16]byte
1647	ttlsStatPol       byte
1648	ttlsStatConn      byte
1649	ttlsSSLProt       uint16
1650	ttlsNegCiph       [2]byte
1651	ttlsSecType       byte
1652	ttlsFIPS140Mode   byte
1653	ttlsUserID        [8]byte
1654	applData          [40]byte
1655	inOldestTime      [8]byte // uint64
1656	outOldestTime     [8]byte // uint64
1657	tcpTrustedPartner byte
1658	_                 [3]byte
1659	bulkDataIntfName  [16]byte
1660	ttlsNegCiph4      [4]byte
1661	smcReason         uint32
1662	lclSMCLinkId      uint32
1663	rmtSMCLinkId      uint32
1664	smcStatus         byte
1665	smcFlags          byte
1666	_                 [2]byte
1667	rcvWnd            uint32
1668	lclSMCBufSz       uint32
1669	rmtSMCBufSz       uint32
1670	ttlsSessID        [32]byte
1671	ttlsSessIDLen     int16
1672	_                 [1]byte
1673	smcDStatus        byte
1674	smcDReason        uint32
1675}
1676
1677var svcNameTable [][]byte = [][]byte{
1678	[]byte("\xc5\xe9\xc2\xd5\xd4\xc9\xc6\xf4"), // svc_EZBNMIF4
1679}
1680
1681const (
1682	svc_EZBNMIF4 = 0
1683)
1684
1685func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) {
1686	jobname := []byte("\x5c\x40\x40\x40\x40\x40\x40\x40") // "*"
1687	responseBuffer := [4096]byte{0}
1688	var bufferAlet, reasonCode uint32 = 0, 0
1689	var bufferLen, returnValue, returnCode int32 = 4096, 0, 0
1690
1691	dsa := [18]uint64{0}
1692	var argv [7]unsafe.Pointer
1693	argv[0] = unsafe.Pointer(&jobname[0])
1694	argv[1] = unsafe.Pointer(&responseBuffer[0])
1695	argv[2] = unsafe.Pointer(&bufferAlet)
1696	argv[3] = unsafe.Pointer(&bufferLen)
1697	argv[4] = unsafe.Pointer(&returnValue)
1698	argv[5] = unsafe.Pointer(&returnCode)
1699	argv[6] = unsafe.Pointer(&reasonCode)
1700
1701	request := (*struct {
1702		header nwmHeader
1703		filter nwmFilter
1704	})(unsafe.Pointer(&responseBuffer[0]))
1705
1706	EZBNMIF4 := svcLoad(&svcNameTable[svc_EZBNMIF4][0])
1707	if EZBNMIF4 == nil {
1708		return nil, errnoErr(EINVAL)
1709	}
1710
1711	// GetGlobalStats EZBNMIF4 call
1712	request.header.ident = nwmHeaderIdentifier
1713	request.header.length = uint32(unsafe.Sizeof(request.header))
1714	request.header.version = nwmCurrentVer
1715	request.header.nwmType = nwmGlobalStatsType
1716	request.header.options = 0x80000000
1717
1718	svcCall(EZBNMIF4, &argv[0], &dsa[0])
1719
1720	// outputDesc field is filled by EZBNMIF4 on success
1721	if returnCode != 0 || request.header.outputDesc.offset == 0 {
1722		return nil, errnoErr(EINVAL)
1723	}
1724
1725	// Check that EZBNMIF4 returned a nwmRecHeader
1726	recHeader := (*nwmRecHeader)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
1727	if recHeader.ident != nwmRecHeaderIdentifier {
1728		return nil, errnoErr(EINVAL)
1729	}
1730
1731	// Parse nwmTriplets to get offsets of returned entries
1732	var sections []*uint64
1733	var sectionDesc *nwmTriplet = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[0]))
1734	for i := uint32(0); i < uint32(recHeader.number); i++ {
1735		offset := request.header.outputDesc.offset + uint32(unsafe.Sizeof(*recHeader)) + i*uint32(unsafe.Sizeof(*sectionDesc))
1736		sectionDesc = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[offset]))
1737		for j := uint32(0); j < sectionDesc.number; j++ {
1738			offset = request.header.outputDesc.offset + sectionDesc.offset + j*sectionDesc.length
1739			sections = append(sections, (*uint64)(unsafe.Pointer(&responseBuffer[offset])))
1740		}
1741	}
1742
1743	// Find nwmTCPStatsEntry in returned entries
1744	var tcpStats *nwmTCPStatsEntry = nil
1745	for _, ptr := range sections {
1746		switch *ptr {
1747		case nwmTCPStatsIdentifier:
1748			if tcpStats != nil {
1749				return nil, errnoErr(EINVAL)
1750			}
1751			tcpStats = (*nwmTCPStatsEntry)(unsafe.Pointer(ptr))
1752		case nwmIPStatsIdentifier:
1753		case nwmIPGStatsIdentifier:
1754		case nwmUDPStatsIdentifier:
1755		case nwmICMPGStatsEntry:
1756		case nwmICMPTStatsEntry:
1757		default:
1758			return nil, errnoErr(EINVAL)
1759		}
1760	}
1761	if tcpStats == nil {
1762		return nil, errnoErr(EINVAL)
1763	}
1764
1765	// GetConnectionDetail EZBNMIF4 call
1766	responseBuffer = [4096]byte{0}
1767	dsa = [18]uint64{0}
1768	bufferAlet, reasonCode = 0, 0
1769	bufferLen, returnValue, returnCode = 4096, 0, 0
1770	nameptr := (*uint32)(unsafe.Pointer(uintptr(0x21c))) // Get jobname of current process
1771	nameptr = (*uint32)(unsafe.Pointer(uintptr(*nameptr + 12)))
1772	argv[0] = unsafe.Pointer(uintptr(*nameptr))
1773
1774	request.header.ident = nwmHeaderIdentifier
1775	request.header.length = uint32(unsafe.Sizeof(request.header))
1776	request.header.version = nwmCurrentVer
1777	request.header.nwmType = nwmTCPConnType
1778	request.header.options = 0x80000000
1779
1780	request.filter.ident = nwmFilterIdentifier
1781
1782	var localSockaddr RawSockaddrAny
1783	socklen := _Socklen(SizeofSockaddrAny)
1784	err := getsockname(fd, &localSockaddr, &socklen)
1785	if err != nil {
1786		return nil, errnoErr(EINVAL)
1787	}
1788	if localSockaddr.Addr.Family == AF_INET {
1789		localSockaddr := (*RawSockaddrInet4)(unsafe.Pointer(&localSockaddr.Addr))
1790		localSockFilter := (*RawSockaddrInet4)(unsafe.Pointer(&request.filter.local[0]))
1791		localSockFilter.Family = AF_INET
1792		var i int
1793		for i = 0; i < 4; i++ {
1794			if localSockaddr.Addr[i] != 0 {
1795				break
1796			}
1797		}
1798		if i != 4 {
1799			request.filter.flags |= nwmFilterLclAddrMask
1800			for i = 0; i < 4; i++ {
1801				localSockFilter.Addr[i] = localSockaddr.Addr[i]
1802			}
1803		}
1804		if localSockaddr.Port != 0 {
1805			request.filter.flags |= nwmFilterLclPortMask
1806			localSockFilter.Port = localSockaddr.Port
1807		}
1808	} else if localSockaddr.Addr.Family == AF_INET6 {
1809		localSockaddr := (*RawSockaddrInet6)(unsafe.Pointer(&localSockaddr.Addr))
1810		localSockFilter := (*RawSockaddrInet6)(unsafe.Pointer(&request.filter.local[0]))
1811		localSockFilter.Family = AF_INET6
1812		var i int
1813		for i = 0; i < 16; i++ {
1814			if localSockaddr.Addr[i] != 0 {
1815				break
1816			}
1817		}
1818		if i != 16 {
1819			request.filter.flags |= nwmFilterLclAddrMask
1820			for i = 0; i < 16; i++ {
1821				localSockFilter.Addr[i] = localSockaddr.Addr[i]
1822			}
1823		}
1824		if localSockaddr.Port != 0 {
1825			request.filter.flags |= nwmFilterLclPortMask
1826			localSockFilter.Port = localSockaddr.Port
1827		}
1828	}
1829
1830	svcCall(EZBNMIF4, &argv[0], &dsa[0])
1831
1832	// outputDesc field is filled by EZBNMIF4 on success
1833	if returnCode != 0 || request.header.outputDesc.offset == 0 {
1834		return nil, errnoErr(EINVAL)
1835	}
1836
1837	// Check that EZBNMIF4 returned a nwmConnEntry
1838	conn := (*nwmConnEntry)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
1839	if conn.ident != nwmTCPConnIdentifier {
1840		return nil, errnoErr(EINVAL)
1841	}
1842
1843	// Copy data from the returned data structures into tcpInfo
1844	// Stats from nwmConnEntry are specific to that connection.
1845	// Stats from nwmTCPStatsEntry are global (to the interface?)
1846	// Fields may not be an exact match. Some fields have no equivalent.
1847	var tcpinfo TCPInfo
1848	tcpinfo.State = uint8(conn.state)
1849	tcpinfo.Ca_state = 0 // dummy
1850	tcpinfo.Retransmits = uint8(tcpStats.retransSegs)
1851	tcpinfo.Probes = uint8(tcpStats.outWinProbes)
1852	tcpinfo.Backoff = 0 // dummy
1853	tcpinfo.Options = 0 // dummy
1854	tcpinfo.Rto = tcpStats.retransTimeouts
1855	tcpinfo.Ato = tcpStats.outDelayAcks
1856	tcpinfo.Snd_mss = conn.sendMSS
1857	tcpinfo.Rcv_mss = conn.sendMSS // dummy
1858	tcpinfo.Unacked = 0            // dummy
1859	tcpinfo.Sacked = 0             // dummy
1860	tcpinfo.Lost = 0               // dummy
1861	tcpinfo.Retrans = conn.reXmtCount
1862	tcpinfo.Fackets = 0 // dummy
1863	tcpinfo.Last_data_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.lastActivity[0])))
1864	tcpinfo.Last_ack_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.outOldestTime[0])))
1865	tcpinfo.Last_data_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
1866	tcpinfo.Last_ack_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
1867	tcpinfo.Pmtu = conn.sendMSS // dummy, NWMIfRouteMtu is a candidate
1868	tcpinfo.Rcv_ssthresh = conn.ssThresh
1869	tcpinfo.Rtt = conn.roundTripTime
1870	tcpinfo.Rttvar = conn.roundTripVar
1871	tcpinfo.Snd_ssthresh = conn.ssThresh // dummy
1872	tcpinfo.Snd_cwnd = conn.congestionWnd
1873	tcpinfo.Advmss = conn.sendMSS        // dummy
1874	tcpinfo.Reordering = 0               // dummy
1875	tcpinfo.Rcv_rtt = conn.roundTripTime // dummy
1876	tcpinfo.Rcv_space = conn.sendMSS     // dummy
1877	tcpinfo.Total_retrans = conn.reXmtCount
1878
1879	svcUnload(&svcNameTable[svc_EZBNMIF4][0], EZBNMIF4)
1880
1881	return &tcpinfo, nil
1882}
1883
1884// GetsockoptString returns the string value of the socket option opt for the
1885// socket associated with fd at the given socket level.
1886func GetsockoptString(fd, level, opt int) (string, error) {
1887	buf := make([]byte, 256)
1888	vallen := _Socklen(len(buf))
1889	err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
1890	if err != nil {
1891		return "", err
1892	}
1893
1894	return ByteSliceToString(buf[:vallen]), nil
1895}
1896
1897func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
1898	var msg Msghdr
1899	var rsa RawSockaddrAny
1900	msg.Name = (*byte)(unsafe.Pointer(&rsa))
1901	msg.Namelen = SizeofSockaddrAny
1902	var iov Iovec
1903	if len(p) > 0 {
1904		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
1905		iov.SetLen(len(p))
1906	}
1907	var dummy byte
1908	if len(oob) > 0 {
1909		// receive at least one normal byte
1910		if len(p) == 0 {
1911			iov.Base = &dummy
1912			iov.SetLen(1)
1913		}
1914		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
1915		msg.SetControllen(len(oob))
1916	}
1917	msg.Iov = &iov
1918	msg.Iovlen = 1
1919	if n, err = recvmsg(fd, &msg, flags); err != nil {
1920		return
1921	}
1922	oobn = int(msg.Controllen)
1923	recvflags = int(msg.Flags)
1924	// source address is only specified if the socket is unconnected
1925	if rsa.Addr.Family != AF_UNSPEC {
1926		// TODO(neeilan): Remove 0 arg added to get this compiling on z/OS
1927		from, err = anyToSockaddr(0, &rsa)
1928	}
1929	return
1930}
1931
1932func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
1933	_, err = SendmsgN(fd, p, oob, to, flags)
1934	return
1935}
1936
1937func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
1938	var ptr unsafe.Pointer
1939	var salen _Socklen
1940	if to != nil {
1941		var err error
1942		ptr, salen, err = to.sockaddr()
1943		if err != nil {
1944			return 0, err
1945		}
1946	}
1947	var msg Msghdr
1948	msg.Name = (*byte)(unsafe.Pointer(ptr))
1949	msg.Namelen = int32(salen)
1950	var iov Iovec
1951	if len(p) > 0 {
1952		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
1953		iov.SetLen(len(p))
1954	}
1955	var dummy byte
1956	if len(oob) > 0 {
1957		// send at least one normal byte
1958		if len(p) == 0 {
1959			iov.Base = &dummy
1960			iov.SetLen(1)
1961		}
1962		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
1963		msg.SetControllen(len(oob))
1964	}
1965	msg.Iov = &iov
1966	msg.Iovlen = 1
1967	if n, err = sendmsg(fd, &msg, flags); err != nil {
1968		return 0, err
1969	}
1970	if len(oob) > 0 && len(p) == 0 {
1971		n = 0
1972	}
1973	return n, nil
1974}
1975
1976func Opendir(name string) (uintptr, error) {
1977	p, err := BytePtrFromString(name)
1978	if err != nil {
1979		return 0, err
1980	}
1981	err = nil
1982	runtime.EnterSyscall()
1983	dir, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___OPENDIR_A<<4, uintptr(unsafe.Pointer(p)))
1984	runtime.ExitSyscall()
1985	runtime.KeepAlive(unsafe.Pointer(p))
1986	if dir == 0 {
1987		err = errnoErr2(e1, e2)
1988	}
1989	return dir, err
1990}
1991
1992// clearsyscall.Errno resets the errno value to 0.
1993func clearErrno()
1994
1995func Closedir(dir uintptr) error {
1996	runtime.EnterSyscall()
1997	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSEDIR<<4, dir)
1998	runtime.ExitSyscall()
1999	if r0 != 0 {
2000		return errnoErr2(e1, e2)
2001	}
2002	return nil
2003}
2004
2005func Seekdir(dir uintptr, pos int) {
2006	runtime.EnterSyscall()
2007	CallLeFuncWithErr(GetZosLibVec()+SYS_SEEKDIR<<4, dir, uintptr(pos))
2008	runtime.ExitSyscall()
2009}
2010
2011func Telldir(dir uintptr) (int, error) {
2012	p, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TELLDIR<<4, dir)
2013	pos := int(p)
2014	if int64(p) == -1 {
2015		return pos, errnoErr2(e1, e2)
2016	}
2017	return pos, nil
2018}
2019
2020// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
2021func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
2022	// struct flock is packed on z/OS. We can't emulate that in Go so
2023	// instead we pack it here.
2024	var flock [24]byte
2025	*(*int16)(unsafe.Pointer(&flock[0])) = lk.Type
2026	*(*int16)(unsafe.Pointer(&flock[2])) = lk.Whence
2027	*(*int64)(unsafe.Pointer(&flock[4])) = lk.Start
2028	*(*int64)(unsafe.Pointer(&flock[12])) = lk.Len
2029	*(*int32)(unsafe.Pointer(&flock[20])) = lk.Pid
2030	runtime.EnterSyscall()
2031	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock)))
2032	runtime.ExitSyscall()
2033	lk.Type = *(*int16)(unsafe.Pointer(&flock[0]))
2034	lk.Whence = *(*int16)(unsafe.Pointer(&flock[2]))
2035	lk.Start = *(*int64)(unsafe.Pointer(&flock[4]))
2036	lk.Len = *(*int64)(unsafe.Pointer(&flock[12]))
2037	lk.Pid = *(*int32)(unsafe.Pointer(&flock[20]))
2038	if r0 == 0 {
2039		return nil
2040	}
2041	return errnoErr2(e1, e2)
2042}
2043
2044func impl_Flock(fd int, how int) (err error) {
2045	runtime.EnterSyscall()
2046	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FLOCK<<4, uintptr(fd), uintptr(how))
2047	runtime.ExitSyscall()
2048	if int64(r0) == -1 {
2049		err = errnoErr2(e1, e2)
2050	}
2051	return
2052}
2053
2054//go:nosplit
2055func get_FlockAddr() *(func(fd int, how int) (err error))
2056
2057var Flock = enter_Flock
2058
2059func validFlock(fp uintptr) bool {
2060	if funcptrtest(GetZosLibVec()+SYS_FLOCK<<4, "") == 0 {
2061		if name, err := getLeFuncName(GetZosLibVec() + SYS_FLOCK<<4); err == nil {
2062			return name == "flock"
2063		}
2064	}
2065	return false
2066}
2067
2068func enter_Flock(fd int, how int) (err error) {
2069	funcref := get_FlockAddr()
2070	if validFlock(GetZosLibVec() + SYS_FLOCK<<4) {
2071		*funcref = impl_Flock
2072	} else {
2073		*funcref = legacyFlock
2074	}
2075	return (*funcref)(fd, how)
2076}
2077
2078func legacyFlock(fd int, how int) error {
2079
2080	var flock_type int16
2081	var fcntl_cmd int
2082
2083	switch how {
2084	case LOCK_SH | LOCK_NB:
2085		flock_type = F_RDLCK
2086		fcntl_cmd = F_SETLK
2087	case LOCK_EX | LOCK_NB:
2088		flock_type = F_WRLCK
2089		fcntl_cmd = F_SETLK
2090	case LOCK_EX:
2091		flock_type = F_WRLCK
2092		fcntl_cmd = F_SETLKW
2093	case LOCK_UN:
2094		flock_type = F_UNLCK
2095		fcntl_cmd = F_SETLKW
2096	default:
2097	}
2098
2099	flock := Flock_t{
2100		Type:   int16(flock_type),
2101		Whence: int16(0),
2102		Start:  int64(0),
2103		Len:    int64(0),
2104		Pid:    int32(Getppid()),
2105	}
2106
2107	err := FcntlFlock(uintptr(fd), fcntl_cmd, &flock)
2108	return err
2109}
2110
2111func Mlock(b []byte) (err error) {
2112	runtime.EnterSyscall()
2113	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP)
2114	runtime.ExitSyscall()
2115	if r0 != 0 {
2116		err = errnoErr2(e1, e2)
2117	}
2118	return
2119}
2120
2121func Mlock2(b []byte, flags int) (err error) {
2122	runtime.EnterSyscall()
2123	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP)
2124	runtime.ExitSyscall()
2125	if r0 != 0 {
2126		err = errnoErr2(e1, e2)
2127	}
2128	return
2129}
2130
2131func Mlockall(flags int) (err error) {
2132	runtime.EnterSyscall()
2133	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP)
2134	runtime.ExitSyscall()
2135	if r0 != 0 {
2136		err = errnoErr2(e1, e2)
2137	}
2138	return
2139}
2140
2141func Munlock(b []byte) (err error) {
2142	runtime.EnterSyscall()
2143	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP)
2144	runtime.ExitSyscall()
2145	if r0 != 0 {
2146		err = errnoErr2(e1, e2)
2147	}
2148	return
2149}
2150
2151func Munlockall() (err error) {
2152	runtime.EnterSyscall()
2153	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP)
2154	runtime.ExitSyscall()
2155	if r0 != 0 {
2156		err = errnoErr2(e1, e2)
2157	}
2158	return
2159}
2160
2161func ClockGettime(clockid int32, ts *Timespec) error {
2162
2163	var ticks_per_sec uint32 = 100 //TODO(kenan): value is currently hardcoded; need sysconf() call otherwise
2164	var nsec_per_sec int64 = 1000000000
2165
2166	if ts == nil {
2167		return EFAULT
2168	}
2169	if clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC {
2170		var nanotime int64 = runtime.Nanotime1()
2171		ts.Sec = nanotime / nsec_per_sec
2172		ts.Nsec = nanotime % nsec_per_sec
2173	} else if clockid == CLOCK_PROCESS_CPUTIME_ID || clockid == CLOCK_THREAD_CPUTIME_ID {
2174		var tm Tms
2175		_, err := Times(&tm)
2176		if err != nil {
2177			return EFAULT
2178		}
2179		ts.Sec = int64(tm.Utime / ticks_per_sec)
2180		ts.Nsec = int64(tm.Utime) * nsec_per_sec / int64(ticks_per_sec)
2181	} else {
2182		return EINVAL
2183	}
2184	return nil
2185}
2186
2187// Chtag
2188
2189//go:nosplit
2190func get_ChtagAddr() *(func(path string, ccsid uint64, textbit uint64) error)
2191
2192var Chtag = enter_Chtag
2193
2194func enter_Chtag(path string, ccsid uint64, textbit uint64) error {
2195	funcref := get_ChtagAddr()
2196	if validSetxattr() {
2197		*funcref = impl_Chtag
2198	} else {
2199		*funcref = legacy_Chtag
2200	}
2201	return (*funcref)(path, ccsid, textbit)
2202}
2203
2204func legacy_Chtag(path string, ccsid uint64, textbit uint64) error {
2205	tag := ccsid<<16 | textbit<<15
2206	var tag_buff [8]byte
2207	DecodeData(tag_buff[:], 8, tag)
2208	return Setxattr(path, "filetag", tag_buff[:], XATTR_REPLACE)
2209}
2210
2211func impl_Chtag(path string, ccsid uint64, textbit uint64) error {
2212	tag := ccsid<<16 | textbit<<15
2213	var tag_buff [4]byte
2214	DecodeData(tag_buff[:], 4, tag)
2215	return Setxattr(path, "system.filetag", tag_buff[:], XATTR_REPLACE)
2216}
2217
2218// End of Chtag
2219
2220// Nanosleep
2221
2222//go:nosplit
2223func get_NanosleepAddr() *(func(time *Timespec, leftover *Timespec) error)
2224
2225var Nanosleep = enter_Nanosleep
2226
2227func enter_Nanosleep(time *Timespec, leftover *Timespec) error {
2228	funcref := get_NanosleepAddr()
2229	if funcptrtest(GetZosLibVec()+SYS_NANOSLEEP<<4, "") == 0 {
2230		*funcref = impl_Nanosleep
2231	} else {
2232		*funcref = legacyNanosleep
2233	}
2234	return (*funcref)(time, leftover)
2235}
2236
2237func impl_Nanosleep(time *Timespec, leftover *Timespec) error {
2238	runtime.EnterSyscall()
2239	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_NANOSLEEP<<4, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)))
2240	runtime.ExitSyscall()
2241	if int64(r0) == -1 {
2242		return errnoErr2(e1, e2)
2243	}
2244	return nil
2245}
2246
2247func legacyNanosleep(time *Timespec, leftover *Timespec) error {
2248	t0 := runtime.Nanotime1()
2249	var secrem uint32
2250	var nsecrem uint32
2251	total := time.Sec*1000000000 + time.Nsec
2252	elapsed := runtime.Nanotime1() - t0
2253	var rv int32
2254	var rc int32
2255	var err error
2256	// repeatedly sleep for 1 second until less than 1 second left
2257	for total-elapsed > 1000000000 {
2258		rv, rc, _ = BpxCondTimedWait(uint32(1), uint32(0), uint32(CW_CONDVAR), &secrem, &nsecrem)
2259		if rv != 0 && rc != 112 { // 112 is EAGAIN
2260			if leftover != nil && rc == 120 { // 120 is EINTR
2261				leftover.Sec = int64(secrem)
2262				leftover.Nsec = int64(nsecrem)
2263			}
2264			err = Errno(rc)
2265			return err
2266		}
2267		elapsed = runtime.Nanotime1() - t0
2268	}
2269	// sleep the remainder
2270	if total > elapsed {
2271		rv, rc, _ = BpxCondTimedWait(uint32(0), uint32(total-elapsed), uint32(CW_CONDVAR), &secrem, &nsecrem)
2272	}
2273	if leftover != nil && rc == 120 {
2274		leftover.Sec = int64(secrem)
2275		leftover.Nsec = int64(nsecrem)
2276	}
2277	if rv != 0 && rc != 112 {
2278		err = Errno(rc)
2279	}
2280	return err
2281}
2282
2283// End of Nanosleep
2284
2285var (
2286	Stdin  = 0
2287	Stdout = 1
2288	Stderr = 2
2289)
2290
2291// Do the interface allocations only once for common
2292// Errno values.
2293var (
2294	errEAGAIN error = syscall.EAGAIN
2295	errEINVAL error = syscall.EINVAL
2296	errENOENT error = syscall.ENOENT
2297)
2298
2299var ZosTraceLevel int
2300var ZosTracefile *os.File
2301
2302var (
2303	signalNameMapOnce sync.Once
2304	signalNameMap     map[string]syscall.Signal
2305)
2306
2307// errnoErr returns common boxed Errno values, to prevent
2308// allocations at runtime.
2309func errnoErr(e Errno) error {
2310	switch e {
2311	case 0:
2312		return nil
2313	case EAGAIN:
2314		return errEAGAIN
2315	case EINVAL:
2316		return errEINVAL
2317	case ENOENT:
2318		return errENOENT
2319	}
2320	return e
2321}
2322
2323var reg *regexp.Regexp
2324
2325// enhanced with zos specific errno2
2326func errnoErr2(e Errno, e2 uintptr) error {
2327	switch e {
2328	case 0:
2329		return nil
2330	case EAGAIN:
2331		return errEAGAIN
2332		/*
2333			Allow the retrieval of errno2 for EINVAL and ENOENT on zos
2334				case EINVAL:
2335					return errEINVAL
2336				case ENOENT:
2337					return errENOENT
2338		*/
2339	}
2340	if ZosTraceLevel > 0 {
2341		var name string
2342		if reg == nil {
2343			reg = regexp.MustCompile("(^unix\\.[^/]+$|.*\\/unix\\.[^/]+$)")
2344		}
2345		i := 1
2346		pc, file, line, ok := runtime.Caller(i)
2347		if ok {
2348			name = runtime.FuncForPC(pc).Name()
2349		}
2350		for ok && reg.MatchString(runtime.FuncForPC(pc).Name()) {
2351			i += 1
2352			pc, file, line, ok = runtime.Caller(i)
2353		}
2354		if ok {
2355			if ZosTracefile == nil {
2356				ZosConsolePrintf("From %s:%d\n", file, line)
2357				ZosConsolePrintf("%s: %s (errno2=0x%x)\n", name, e.Error(), e2)
2358			} else {
2359				fmt.Fprintf(ZosTracefile, "From %s:%d\n", file, line)
2360				fmt.Fprintf(ZosTracefile, "%s: %s (errno2=0x%x)\n", name, e.Error(), e2)
2361			}
2362		} else {
2363			if ZosTracefile == nil {
2364				ZosConsolePrintf("%s (errno2=0x%x)\n", e.Error(), e2)
2365			} else {
2366				fmt.Fprintf(ZosTracefile, "%s (errno2=0x%x)\n", e.Error(), e2)
2367			}
2368		}
2369	}
2370	return e
2371}
2372
2373// ErrnoName returns the error name for error number e.
2374func ErrnoName(e Errno) string {
2375	i := sort.Search(len(errorList), func(i int) bool {
2376		return errorList[i].num >= e
2377	})
2378	if i < len(errorList) && errorList[i].num == e {
2379		return errorList[i].name
2380	}
2381	return ""
2382}
2383
2384// SignalName returns the signal name for signal number s.
2385func SignalName(s syscall.Signal) string {
2386	i := sort.Search(len(signalList), func(i int) bool {
2387		return signalList[i].num >= s
2388	})
2389	if i < len(signalList) && signalList[i].num == s {
2390		return signalList[i].name
2391	}
2392	return ""
2393}
2394
2395// SignalNum returns the syscall.Signal for signal named s,
2396// or 0 if a signal with such name is not found.
2397// The signal name should start with "SIG".
2398func SignalNum(s string) syscall.Signal {
2399	signalNameMapOnce.Do(func() {
2400		signalNameMap = make(map[string]syscall.Signal, len(signalList))
2401		for _, signal := range signalList {
2402			signalNameMap[signal.name] = signal.num
2403		}
2404	})
2405	return signalNameMap[s]
2406}
2407
2408// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
2409func clen(n []byte) int {
2410	i := bytes.IndexByte(n, 0)
2411	if i == -1 {
2412		i = len(n)
2413	}
2414	return i
2415}
2416
2417// Mmap manager, for use by operating system-specific implementations.
2418
2419type mmapper struct {
2420	sync.Mutex
2421	active map[*byte][]byte // active mappings; key is last byte in mapping
2422	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
2423	munmap func(addr uintptr, length uintptr) error
2424}
2425
2426func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
2427	if length <= 0 {
2428		return nil, EINVAL
2429	}
2430
2431	// Set __MAP_64 by default
2432	flags |= __MAP_64
2433
2434	// Map the requested memory.
2435	addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
2436	if errno != nil {
2437		return nil, errno
2438	}
2439
2440	// Slice memory layout
2441	var sl = struct {
2442		addr uintptr
2443		len  int
2444		cap  int
2445	}{addr, length, length}
2446
2447	// Use unsafe to turn sl into a []byte.
2448	b := *(*[]byte)(unsafe.Pointer(&sl))
2449
2450	// Register mapping in m and return it.
2451	p := &b[cap(b)-1]
2452	m.Lock()
2453	defer m.Unlock()
2454	m.active[p] = b
2455	return b, nil
2456}
2457
2458func (m *mmapper) Munmap(data []byte) (err error) {
2459	if len(data) == 0 || len(data) != cap(data) {
2460		return EINVAL
2461	}
2462
2463	// Find the base of the mapping.
2464	p := &data[cap(data)-1]
2465	m.Lock()
2466	defer m.Unlock()
2467	b := m.active[p]
2468	if b == nil || &b[0] != &data[0] {
2469		return EINVAL
2470	}
2471
2472	// Unmap the memory and update m.
2473	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
2474		return errno
2475	}
2476	delete(m.active, p)
2477	return nil
2478}
2479
2480func Read(fd int, p []byte) (n int, err error) {
2481	n, err = read(fd, p)
2482	if raceenabled {
2483		if n > 0 {
2484			raceWriteRange(unsafe.Pointer(&p[0]), n)
2485		}
2486		if err == nil {
2487			raceAcquire(unsafe.Pointer(&ioSync))
2488		}
2489	}
2490	return
2491}
2492
2493func Write(fd int, p []byte) (n int, err error) {
2494	if raceenabled {
2495		raceReleaseMerge(unsafe.Pointer(&ioSync))
2496	}
2497	n, err = write(fd, p)
2498	if raceenabled && n > 0 {
2499		raceReadRange(unsafe.Pointer(&p[0]), n)
2500	}
2501	return
2502}
2503
2504// For testing: clients can set this flag to force
2505// creation of IPv6 sockets to return EAFNOSUPPORT.
2506var SocketDisableIPv6 bool
2507
2508// Sockaddr represents a socket address.
2509type Sockaddr interface {
2510	sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs
2511}
2512
2513// SockaddrInet4 implements the Sockaddr interface for AF_INET type sockets.
2514type SockaddrInet4 struct {
2515	Port int
2516	Addr [4]byte
2517	raw  RawSockaddrInet4
2518}
2519
2520// SockaddrInet6 implements the Sockaddr interface for AF_INET6 type sockets.
2521type SockaddrInet6 struct {
2522	Port   int
2523	ZoneId uint32
2524	Addr   [16]byte
2525	raw    RawSockaddrInet6
2526}
2527
2528// SockaddrUnix implements the Sockaddr interface for AF_UNIX type sockets.
2529type SockaddrUnix struct {
2530	Name string
2531	raw  RawSockaddrUnix
2532}
2533
2534func Bind(fd int, sa Sockaddr) (err error) {
2535	ptr, n, err := sa.sockaddr()
2536	if err != nil {
2537		return err
2538	}
2539	return bind(fd, ptr, n)
2540}
2541
2542func Connect(fd int, sa Sockaddr) (err error) {
2543	ptr, n, err := sa.sockaddr()
2544	if err != nil {
2545		return err
2546	}
2547	return connect(fd, ptr, n)
2548}
2549
2550func Getpeername(fd int) (sa Sockaddr, err error) {
2551	var rsa RawSockaddrAny
2552	var len _Socklen = SizeofSockaddrAny
2553	if err = getpeername(fd, &rsa, &len); err != nil {
2554		return
2555	}
2556	return anyToSockaddr(fd, &rsa)
2557}
2558
2559func GetsockoptByte(fd, level, opt int) (value byte, err error) {
2560	var n byte
2561	vallen := _Socklen(1)
2562	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
2563	return n, err
2564}
2565
2566func GetsockoptInt(fd, level, opt int) (value int, err error) {
2567	var n int32
2568	vallen := _Socklen(4)
2569	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
2570	return int(n), err
2571}
2572
2573func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
2574	vallen := _Socklen(4)
2575	err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
2576	return value, err
2577}
2578
2579func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
2580	var value IPMreq
2581	vallen := _Socklen(SizeofIPMreq)
2582	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
2583	return &value, err
2584}
2585
2586func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
2587	var value IPv6Mreq
2588	vallen := _Socklen(SizeofIPv6Mreq)
2589	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
2590	return &value, err
2591}
2592
2593func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) {
2594	var value IPv6MTUInfo
2595	vallen := _Socklen(SizeofIPv6MTUInfo)
2596	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
2597	return &value, err
2598}
2599
2600func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {
2601	var value ICMPv6Filter
2602	vallen := _Socklen(SizeofICMPv6Filter)
2603	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
2604	return &value, err
2605}
2606
2607func GetsockoptLinger(fd, level, opt int) (*Linger, error) {
2608	var linger Linger
2609	vallen := _Socklen(SizeofLinger)
2610	err := getsockopt(fd, level, opt, unsafe.Pointer(&linger), &vallen)
2611	return &linger, err
2612}
2613
2614func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) {
2615	var tv Timeval
2616	vallen := _Socklen(unsafe.Sizeof(tv))
2617	err := getsockopt(fd, level, opt, unsafe.Pointer(&tv), &vallen)
2618	return &tv, err
2619}
2620
2621func GetsockoptUint64(fd, level, opt int) (value uint64, err error) {
2622	var n uint64
2623	vallen := _Socklen(8)
2624	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
2625	return n, err
2626}
2627
2628func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
2629	var rsa RawSockaddrAny
2630	var len _Socklen = SizeofSockaddrAny
2631	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
2632		return
2633	}
2634	if rsa.Addr.Family != AF_UNSPEC {
2635		from, err = anyToSockaddr(fd, &rsa)
2636	}
2637	return
2638}
2639
2640func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
2641	ptr, n, err := to.sockaddr()
2642	if err != nil {
2643		return err
2644	}
2645	return sendto(fd, p, flags, ptr, n)
2646}
2647
2648func SetsockoptByte(fd, level, opt int, value byte) (err error) {
2649	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
2650}
2651
2652func SetsockoptInt(fd, level, opt int, value int) (err error) {
2653	var n = int32(value)
2654	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
2655}
2656
2657func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
2658	return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
2659}
2660
2661func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
2662	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq)
2663}
2664
2665func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
2666	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq)
2667}
2668
2669func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
2670	return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
2671}
2672
2673func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
2674	return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger)
2675}
2676
2677func SetsockoptString(fd, level, opt int, s string) (err error) {
2678	var p unsafe.Pointer
2679	if len(s) > 0 {
2680		p = unsafe.Pointer(&[]byte(s)[0])
2681	}
2682	return setsockopt(fd, level, opt, p, uintptr(len(s)))
2683}
2684
2685func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
2686	return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv))
2687}
2688
2689func SetsockoptUint64(fd, level, opt int, value uint64) (err error) {
2690	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 8)
2691}
2692
2693func Socket(domain, typ, proto int) (fd int, err error) {
2694	if domain == AF_INET6 && SocketDisableIPv6 {
2695		return -1, EAFNOSUPPORT
2696	}
2697	fd, err = socket(domain, typ, proto)
2698	return
2699}
2700
2701func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
2702	var fdx [2]int32
2703	err = socketpair(domain, typ, proto, &fdx)
2704	if err == nil {
2705		fd[0] = int(fdx[0])
2706		fd[1] = int(fdx[1])
2707	}
2708	return
2709}
2710
2711var ioSync int64
2712
2713func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
2714
2715func SetNonblock(fd int, nonblocking bool) (err error) {
2716	flag, err := fcntl(fd, F_GETFL, 0)
2717	if err != nil {
2718		return err
2719	}
2720	if nonblocking {
2721		flag |= O_NONBLOCK
2722	} else {
2723		flag &= ^O_NONBLOCK
2724	}
2725	_, err = fcntl(fd, F_SETFL, flag)
2726	return err
2727}
2728
2729// Exec calls execve(2), which replaces the calling executable in the process
2730// tree. argv0 should be the full path to an executable ("/bin/ls") and the
2731// executable name should also be the first argument in argv (["ls", "-l"]).
2732// envv are the environment variables that should be passed to the new
2733// process (["USER=go", "PWD=/tmp"]).
2734func Exec(argv0 string, argv []string, envv []string) error {
2735	return syscall.Exec(argv0, argv, envv)
2736}
2737
2738func Getag(path string) (ccsid uint16, flag uint16, err error) {
2739	var val [8]byte
2740	sz, err := Getxattr(path, "ccsid", val[:])
2741	if err != nil {
2742		return
2743	}
2744	ccsid = uint16(EncodeData(val[0:sz]))
2745	sz, err = Getxattr(path, "flags", val[:])
2746	if err != nil {
2747		return
2748	}
2749	flag = uint16(EncodeData(val[0:sz]) >> 15)
2750	return
2751}
2752
2753// Mount begin
2754func impl_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
2755	var _p0 *byte
2756	_p0, err = BytePtrFromString(source)
2757	if err != nil {
2758		return
2759	}
2760	var _p1 *byte
2761	_p1, err = BytePtrFromString(target)
2762	if err != nil {
2763		return
2764	}
2765	var _p2 *byte
2766	_p2, err = BytePtrFromString(fstype)
2767	if err != nil {
2768		return
2769	}
2770	var _p3 *byte
2771	_p3, err = BytePtrFromString(data)
2772	if err != nil {
2773		return
2774	}
2775	runtime.EnterSyscall()
2776	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MOUNT1_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(_p3)))
2777	runtime.ExitSyscall()
2778	if int64(r0) == -1 {
2779		err = errnoErr2(e1, e2)
2780	}
2781	return
2782}
2783
2784//go:nosplit
2785func get_MountAddr() *(func(source string, target string, fstype string, flags uintptr, data string) (err error))
2786
2787var Mount = enter_Mount
2788
2789func enter_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
2790	funcref := get_MountAddr()
2791	if validMount() {
2792		*funcref = impl_Mount
2793	} else {
2794		*funcref = legacyMount
2795	}
2796	return (*funcref)(source, target, fstype, flags, data)
2797}
2798
2799func legacyMount(source string, target string, fstype string, flags uintptr, data string) (err error) {
2800	if needspace := 8 - len(fstype); needspace <= 0 {
2801		fstype = fstype[0:8]
2802	} else {
2803		fstype += "        "[0:needspace]
2804	}
2805	return mount_LE(target, source, fstype, uint32(flags), int32(len(data)), data)
2806}
2807
2808func validMount() bool {
2809	if funcptrtest(GetZosLibVec()+SYS___MOUNT1_A<<4, "") == 0 {
2810		if name, err := getLeFuncName(GetZosLibVec() + SYS___MOUNT1_A<<4); err == nil {
2811			return name == "__mount1_a"
2812		}
2813	}
2814	return false
2815}
2816
2817// Mount end
2818
2819// Unmount begin
2820func impl_Unmount(target string, flags int) (err error) {
2821	var _p0 *byte
2822	_p0, err = BytePtrFromString(target)
2823	if err != nil {
2824		return
2825	}
2826	runtime.EnterSyscall()
2827	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UMOUNT2_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(flags))
2828	runtime.ExitSyscall()
2829	if int64(r0) == -1 {
2830		err = errnoErr2(e1, e2)
2831	}
2832	return
2833}
2834
2835//go:nosplit
2836func get_UnmountAddr() *(func(target string, flags int) (err error))
2837
2838var Unmount = enter_Unmount
2839
2840func enter_Unmount(target string, flags int) (err error) {
2841	funcref := get_UnmountAddr()
2842	if funcptrtest(GetZosLibVec()+SYS___UMOUNT2_A<<4, "") == 0 {
2843		*funcref = impl_Unmount
2844	} else {
2845		*funcref = legacyUnmount
2846	}
2847	return (*funcref)(target, flags)
2848}
2849
2850func legacyUnmount(name string, mtm int) (err error) {
2851	// mountpoint is always a full path and starts with a '/'
2852	// check if input string is not a mountpoint but a filesystem name
2853	if name[0] != '/' {
2854		return unmount_LE(name, mtm)
2855	}
2856	// treat name as mountpoint
2857	b2s := func(arr []byte) string {
2858		var str string
2859		for i := 0; i < len(arr); i++ {
2860			if arr[i] == 0 {
2861				str = string(arr[:i])
2862				break
2863			}
2864		}
2865		return str
2866	}
2867	var buffer struct {
2868		header W_Mnth
2869		fsinfo [64]W_Mntent
2870	}
2871	fs_count, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer)))
2872	if err == nil {
2873		err = EINVAL
2874		for i := 0; i < fs_count; i++ {
2875			if b2s(buffer.fsinfo[i].Mountpoint[:]) == name {
2876				err = unmount_LE(b2s(buffer.fsinfo[i].Fsname[:]), mtm)
2877				break
2878			}
2879		}
2880	} else if fs_count == 0 {
2881		err = EINVAL
2882	}
2883	return err
2884}
2885
2886// Unmount end
2887
2888func direntIno(buf []byte) (uint64, bool) {
2889	return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
2890}
2891
2892func direntReclen(buf []byte) (uint64, bool) {
2893	return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
2894}
2895
2896func direntNamlen(buf []byte) (uint64, bool) {
2897	reclen, ok := direntReclen(buf)
2898	if !ok {
2899		return 0, false
2900	}
2901	return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
2902}
2903
2904func direntLeToDirentUnix(dirent *direntLE, dir uintptr, path string) (Dirent, error) {
2905	var d Dirent
2906
2907	d.Ino = uint64(dirent.Ino)
2908	offset, err := Telldir(dir)
2909	if err != nil {
2910		return d, err
2911	}
2912
2913	d.Off = int64(offset)
2914	s := string(bytes.Split(dirent.Name[:], []byte{0})[0])
2915	copy(d.Name[:], s)
2916
2917	d.Reclen = uint16(24 + len(d.NameString()))
2918	var st Stat_t
2919	path = path + "/" + s
2920	err = Lstat(path, &st)
2921	if err != nil {
2922		return d, err
2923	}
2924
2925	d.Type = uint8(st.Mode >> 24)
2926	return d, err
2927}
2928
2929func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
2930	// Simulation of Getdirentries port from the Darwin implementation.
2931	// COMMENTS FROM DARWIN:
2932	// It's not the full required semantics, but should handle the case
2933	// of calling Getdirentries or ReadDirent repeatedly.
2934	// It won't handle assigning the results of lseek to *basep, or handle
2935	// the directory being edited underfoot.
2936
2937	skip, err := Seek(fd, 0, 1 /* SEEK_CUR */)
2938	if err != nil {
2939		return 0, err
2940	}
2941
2942	// Get path from fd to avoid unavailable call (fdopendir)
2943	path, err := ZosFdToPath(fd)
2944	if err != nil {
2945		return 0, err
2946	}
2947	d, err := Opendir(path)
2948	if err != nil {
2949		return 0, err
2950	}
2951	defer Closedir(d)
2952
2953	var cnt int64
2954	for {
2955		var entryLE direntLE
2956		var entrypLE *direntLE
2957		e := Readdir_r(d, &entryLE, &entrypLE)
2958		if e != nil {
2959			return n, e
2960		}
2961		if entrypLE == nil {
2962			break
2963		}
2964		if skip > 0 {
2965			skip--
2966			cnt++
2967			continue
2968		}
2969
2970		// Dirent on zos has a different structure
2971		entry, e := direntLeToDirentUnix(&entryLE, d, path)
2972		if e != nil {
2973			return n, e
2974		}
2975
2976		reclen := int(entry.Reclen)
2977		if reclen > len(buf) {
2978			// Not enough room. Return for now.
2979			// The counter will let us know where we should start up again.
2980			// Note: this strategy for suspending in the middle and
2981			// restarting is O(n^2) in the length of the directory. Oh well.
2982			break
2983		}
2984
2985		// Copy entry into return buffer.
2986		s := unsafe.Slice((*byte)(unsafe.Pointer(&entry)), reclen)
2987		copy(buf, s)
2988
2989		buf = buf[reclen:]
2990		n += reclen
2991		cnt++
2992	}
2993	// Set the seek offset of the input fd to record
2994	// how many files we've already returned.
2995	_, err = Seek(fd, cnt, 0 /* SEEK_SET */)
2996	if err != nil {
2997		return n, err
2998	}
2999
3000	return n, nil
3001}
3002
3003func Err2ad() (eadd *int) {
3004	r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS___ERR2AD<<4)
3005	eadd = (*int)(unsafe.Pointer(r0))
3006	return
3007}
3008
3009func ZosConsolePrintf(format string, v ...interface{}) (int, error) {
3010	type __cmsg struct {
3011		_            uint16
3012		_            [2]uint8
3013		__msg_length uint32
3014		__msg        uintptr
3015		_            [4]uint8
3016	}
3017	msg := fmt.Sprintf(format, v...)
3018	strptr := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&msg)).Data)
3019	len := (*reflect.StringHeader)(unsafe.Pointer(&msg)).Len
3020	cmsg := __cmsg{__msg_length: uint32(len), __msg: uintptr(strptr)}
3021	cmd := uint32(0)
3022	runtime.EnterSyscall()
3023	rc, err2, err1 := CallLeFuncWithErr(GetZosLibVec()+SYS_____CONSOLE_A<<4, uintptr(unsafe.Pointer(&cmsg)), 0, uintptr(unsafe.Pointer(&cmd)))
3024	runtime.ExitSyscall()
3025	if rc != 0 {
3026		return 0, fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2)
3027	}
3028	return 0, nil
3029}
3030func ZosStringToEbcdicBytes(str string, nullterm bool) (ebcdicBytes []byte) {
3031	if nullterm {
3032		ebcdicBytes = []byte(str + "\x00")
3033	} else {
3034		ebcdicBytes = []byte(str)
3035	}
3036	A2e(ebcdicBytes)
3037	return
3038}
3039func ZosEbcdicBytesToString(b []byte, trimRight bool) (str string) {
3040	res := make([]byte, len(b))
3041	copy(res, b)
3042	E2a(res)
3043	if trimRight {
3044		str = string(bytes.TrimRight(res, " \x00"))
3045	} else {
3046		str = string(res)
3047	}
3048	return
3049}
3050
3051func fdToPath(dirfd int) (path string, err error) {
3052	var buffer [1024]byte
3053	// w_ctrl()
3054	ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4,
3055		[]uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))})
3056	if ret == 0 {
3057		zb := bytes.IndexByte(buffer[:], 0)
3058		if zb == -1 {
3059			zb = len(buffer)
3060		}
3061		// __e2a_l()
3062		runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4,
3063			[]uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)})
3064		return string(buffer[:zb]), nil
3065	}
3066	// __errno()
3067	errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4,
3068		[]uintptr{}))))
3069	// __errno2()
3070	errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4,
3071		[]uintptr{}))
3072	// strerror_r()
3073	ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4,
3074		[]uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024})
3075	if ret == 0 {
3076		zb := bytes.IndexByte(buffer[:], 0)
3077		if zb == -1 {
3078			zb = len(buffer)
3079		}
3080		return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2)
3081	} else {
3082		return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2)
3083	}
3084}
3085
3086func impl_Mkfifoat(dirfd int, path string, mode uint32) (err error) {
3087	var _p0 *byte
3088	_p0, err = BytePtrFromString(path)
3089	if err != nil {
3090		return
3091	}
3092	runtime.EnterSyscall()
3093	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKFIFOAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
3094	runtime.ExitSyscall()
3095	if int64(r0) == -1 {
3096		err = errnoErr2(e1, e2)
3097	}
3098	return
3099}
3100
3101//go:nosplit
3102func get_MkfifoatAddr() *(func(dirfd int, path string, mode uint32) (err error))
3103
3104var Mkfifoat = enter_Mkfifoat
3105
3106func enter_Mkfifoat(dirfd int, path string, mode uint32) (err error) {
3107	funcref := get_MkfifoatAddr()
3108	if funcptrtest(GetZosLibVec()+SYS___MKFIFOAT_A<<4, "") == 0 {
3109		*funcref = impl_Mkfifoat
3110	} else {
3111		*funcref = legacy_Mkfifoat
3112	}
3113	return (*funcref)(dirfd, path, mode)
3114}
3115
3116func legacy_Mkfifoat(dirfd int, path string, mode uint32) (err error) {
3117	dirname, err := ZosFdToPath(dirfd)
3118	if err != nil {
3119		return err
3120	}
3121	return Mkfifo(dirname+"/"+path, mode)
3122}
3123
3124//sys	Posix_openpt(oflag int) (fd int, err error) = SYS_POSIX_OPENPT
3125//sys	Grantpt(fildes int) (rc int, err error) = SYS_GRANTPT
3126//sys	Unlockpt(fildes int) (rc int, err error) = SYS_UNLOCKPT
3127
3128func fcntlAsIs(fd uintptr, cmd int, arg uintptr) (val int, err error) {
3129	runtime.EnterSyscall()
3130	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), arg)
3131	runtime.ExitSyscall()
3132	val = int(r0)
3133	if int64(r0) == -1 {
3134		err = errnoErr2(e1, e2)
3135	}
3136	return
3137}
3138
3139func Fcntl(fd uintptr, cmd int, op interface{}) (ret int, err error) {
3140	switch op.(type) {
3141	case *Flock_t:
3142		err = FcntlFlock(fd, cmd, op.(*Flock_t))
3143		if err != nil {
3144			ret = -1
3145		}
3146		return
3147	case int:
3148		return FcntlInt(fd, cmd, op.(int))
3149	case *F_cnvrt:
3150		return fcntlAsIs(fd, cmd, uintptr(unsafe.Pointer(op.(*F_cnvrt))))
3151	case unsafe.Pointer:
3152		return fcntlAsIs(fd, cmd, uintptr(op.(unsafe.Pointer)))
3153	default:
3154		return -1, EINVAL
3155	}
3156	return
3157}
3158
3159func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
3160	if raceenabled {
3161		raceReleaseMerge(unsafe.Pointer(&ioSync))
3162	}
3163	return sendfile(outfd, infd, offset, count)
3164}
3165
3166func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
3167	// TODO: use LE call instead if the call is implemented
3168	originalOffset, err := Seek(infd, 0, SEEK_CUR)
3169	if err != nil {
3170		return -1, err
3171	}
3172	//start reading data from in_fd
3173	if offset != nil {
3174		_, err := Seek(infd, *offset, SEEK_SET)
3175		if err != nil {
3176			return -1, err
3177		}
3178	}
3179
3180	buf := make([]byte, count)
3181	readBuf := make([]byte, 0)
3182	var n int = 0
3183	for i := 0; i < count; i += n {
3184		n, err := Read(infd, buf)
3185		if n == 0 {
3186			if err != nil {
3187				return -1, err
3188			} else { // EOF
3189				break
3190			}
3191		}
3192		readBuf = append(readBuf, buf...)
3193		buf = buf[0:0]
3194	}
3195
3196	n2, err := Write(outfd, readBuf)
3197	if err != nil {
3198		return -1, err
3199	}
3200
3201	//When sendfile() returns, this variable will be set to the
3202	// offset of the byte following the last byte that was read.
3203	if offset != nil {
3204		*offset = *offset + int64(n)
3205		// If offset is not NULL, then sendfile() does not modify the file
3206		// offset of in_fd
3207		_, err := Seek(infd, originalOffset, SEEK_SET)
3208		if err != nil {
3209			return -1, err
3210		}
3211	}
3212	return n2, nil
3213}