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
771//sys   Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A
772//sysnb	Getgid() (gid int)
773//sysnb	Getpid() (pid int)
774//sysnb	Getpgid(pid int) (pgid int, err error) = SYS_GETPGID
775
776func Getpgrp() (pid int) {
777	pid, _ = Getpgid(0)
778	return
779}
780
781//sysnb	Getppid() (pid int)
782//sys	Getpriority(which int, who int) (prio int, err error)
783//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_GETRLIMIT
784
785//sysnb getrusage(who int, rusage *rusage_zos) (err error) = SYS_GETRUSAGE
786
787func Getrusage(who int, rusage *Rusage) (err error) {
788	var ruz rusage_zos
789	err = getrusage(who, &ruz)
790	//Only the first two fields of Rusage are set
791	rusage.Utime.Sec = ruz.Utime.Sec
792	rusage.Utime.Usec = int64(ruz.Utime.Usec)
793	rusage.Stime.Sec = ruz.Stime.Sec
794	rusage.Stime.Usec = int64(ruz.Stime.Usec)
795	return
796}
797
798//sys	Getegid() (egid int) = SYS_GETEGID
799//sys	Geteuid() (euid int) = SYS_GETEUID
800//sysnb Getsid(pid int) (sid int, err error) = SYS_GETSID
801//sysnb	Getuid() (uid int)
802//sysnb	Kill(pid int, sig Signal) (err error)
803//sys	Lchown(path string, uid int, gid int) (err error) = SYS___LCHOWN_A
804//sys	Link(path string, link string) (err error) = SYS___LINK_A
805//sys	Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) = SYS___LINKAT_A
806//sys	Listen(s int, n int) (err error)
807//sys	lstat(path string, stat *Stat_LE_t) (err error) = SYS___LSTAT_A
808
809func Lstat(path string, stat *Stat_t) (err error) {
810	var statLE Stat_LE_t
811	err = lstat(path, &statLE)
812	copyStat(stat, &statLE)
813	return
814}
815
816// for checking symlinks begins with $VERSION/ $SYSNAME/ $SYSSYMR/ $SYSSYMA/
817func isSpecialPath(path []byte) (v bool) {
818	var special = [4][8]byte{
819		[8]byte{'V', 'E', 'R', 'S', 'I', 'O', 'N', '/'},
820		[8]byte{'S', 'Y', 'S', 'N', 'A', 'M', 'E', '/'},
821		[8]byte{'S', 'Y', 'S', 'S', 'Y', 'M', 'R', '/'},
822		[8]byte{'S', 'Y', 'S', 'S', 'Y', 'M', 'A', '/'}}
823
824	var i, j int
825	for i = 0; i < len(special); i++ {
826		for j = 0; j < len(special[i]); j++ {
827			if path[j] != special[i][j] {
828				break
829			}
830		}
831		if j == len(special[i]) {
832			return true
833		}
834	}
835	return false
836}
837
838func realpath(srcpath string, abspath []byte) (pathlen int, errno int) {
839	var source [1024]byte
840	copy(source[:], srcpath)
841	source[len(srcpath)] = 0
842	ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___REALPATH_A<<4, //__realpath_a()
843		[]uintptr{uintptr(unsafe.Pointer(&source[0])),
844			uintptr(unsafe.Pointer(&abspath[0]))})
845	if ret != 0 {
846		index := bytes.IndexByte(abspath[:], byte(0))
847		if index != -1 {
848			return index, 0
849		}
850	} else {
851		errptr := (*int)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{}))) //__errno()
852		return 0, *errptr
853	}
854	return 0, 245 // EBADDATA   245
855}
856
857func Readlink(path string, buf []byte) (n int, err error) {
858	var _p0 *byte
859	_p0, err = BytePtrFromString(path)
860	if err != nil {
861		return
862	}
863	var _p1 unsafe.Pointer
864	if len(buf) > 0 {
865		_p1 = unsafe.Pointer(&buf[0])
866	} else {
867		_p1 = unsafe.Pointer(&_zero)
868	}
869	n = int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___READLINK_A<<4,
870		[]uintptr{uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))}))
871	runtime.KeepAlive(unsafe.Pointer(_p0))
872	if n == -1 {
873		value := *(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{})))
874		err = errnoErr(Errno(value))
875	} else {
876		if buf[0] == '$' {
877			if isSpecialPath(buf[1:9]) {
878				cnt, err1 := realpath(path, buf)
879				if err1 == 0 {
880					n = cnt
881				}
882			}
883		}
884	}
885	return
886}
887
888func impl_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
889	var _p0 *byte
890	_p0, err = BytePtrFromString(path)
891	if err != nil {
892		return
893	}
894	var _p1 unsafe.Pointer
895	if len(buf) > 0 {
896		_p1 = unsafe.Pointer(&buf[0])
897	} else {
898		_p1 = unsafe.Pointer(&_zero)
899	}
900	runtime.EnterSyscall()
901	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READLINKAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
902	runtime.ExitSyscall()
903	n = int(r0)
904	if int64(r0) == -1 {
905		err = errnoErr2(e1, e2)
906		return n, err
907	} else {
908		if buf[0] == '$' {
909			if isSpecialPath(buf[1:9]) {
910				cnt, err1 := realpath(path, buf)
911				if err1 == 0 {
912					n = cnt
913				}
914			}
915		}
916	}
917	return
918}
919
920//go:nosplit
921func get_ReadlinkatAddr() *(func(dirfd int, path string, buf []byte) (n int, err error))
922
923var Readlinkat = enter_Readlinkat
924
925func enter_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
926	funcref := get_ReadlinkatAddr()
927	if funcptrtest(GetZosLibVec()+SYS___READLINKAT_A<<4, "") == 0 {
928		*funcref = impl_Readlinkat
929	} else {
930		*funcref = error_Readlinkat
931	}
932	return (*funcref)(dirfd, path, buf)
933}
934
935func error_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
936	n = -1
937	err = ENOSYS
938	return
939}
940
941//sys	Mkdir(path string, mode uint32) (err error) = SYS___MKDIR_A
942//sys	Mkdirat(dirfd int, path string, mode uint32) (err error) = SYS___MKDIRAT_A
943//sys   Mkfifo(path string, mode uint32) (err error) = SYS___MKFIFO_A
944//sys	Mknod(path string, mode uint32, dev int) (err error) = SYS___MKNOD_A
945//sys	Mknodat(dirfd int, path string, mode uint32, dev int) (err error) = SYS___MKNODAT_A
946//sys	PivotRoot(newroot string, oldroot string) (err error) = SYS___PIVOT_ROOT_A
947//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
948//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
949//sys	Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) = SYS___PRCTL_A
950//sysnb	Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT
951//sys	Rename(from string, to string) (err error) = SYS___RENAME_A
952//sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) = SYS___RENAMEAT_A
953//sys	Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) = SYS___RENAMEAT2_A
954//sys	Rmdir(path string) (err error) = SYS___RMDIR_A
955//sys   Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
956//sys	Setegid(egid int) (err error) = SYS_SETEGID
957//sys	Seteuid(euid int) (err error) = SYS_SETEUID
958//sys	Sethostname(p []byte) (err error) = SYS___SETHOSTNAME_A
959//sys   Setns(fd int, nstype int) (err error) = SYS_SETNS
960//sys	Setpriority(which int, who int, prio int) (err error)
961//sysnb	Setpgid(pid int, pgid int) (err error) = SYS_SETPGID
962//sysnb	Setrlimit(resource int, lim *Rlimit) (err error)
963//sysnb	Setregid(rgid int, egid int) (err error) = SYS_SETREGID
964//sysnb	Setreuid(ruid int, euid int) (err error) = SYS_SETREUID
965//sysnb	Setsid() (pid int, err error) = SYS_SETSID
966//sys	Setuid(uid int) (err error) = SYS_SETUID
967//sys	Setgid(uid int) (err error) = SYS_SETGID
968//sys	Shutdown(fd int, how int) (err error)
969//sys	stat(path string, statLE *Stat_LE_t) (err error) = SYS___STAT_A
970
971func Stat(path string, sta *Stat_t) (err error) {
972	var statLE Stat_LE_t
973	err = stat(path, &statLE)
974	copyStat(sta, &statLE)
975	return
976}
977
978//sys	Symlink(path string, link string) (err error) = SYS___SYMLINK_A
979//sys	Symlinkat(oldPath string, dirfd int, newPath string) (err error) = SYS___SYMLINKAT_A
980//sys	Sync() = SYS_SYNC
981//sys	Truncate(path string, length int64) (err error) = SYS___TRUNCATE_A
982//sys	Tcgetattr(fildes int, termptr *Termios) (err error) = SYS_TCGETATTR
983//sys	Tcsetattr(fildes int, when int, termptr *Termios) (err error) = SYS_TCSETATTR
984//sys	Umask(mask int) (oldmask int)
985//sys	Unlink(path string) (err error) = SYS___UNLINK_A
986//sys	Unlinkat(dirfd int, path string, flags int) (err error) = SYS___UNLINKAT_A
987//sys	Utime(path string, utim *Utimbuf) (err error) = SYS___UTIME_A
988
989//sys	open(path string, mode int, perm uint32) (fd int, err error) = SYS___OPEN_A
990
991func Open(path string, mode int, perm uint32) (fd int, err error) {
992	if mode&O_ACCMODE == 0 {
993		mode |= O_RDONLY
994	}
995	return open(path, mode, perm)
996}
997
998//sys	openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) = SYS___OPENAT_A
999
1000func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
1001	if flags&O_ACCMODE == 0 {
1002		flags |= O_RDONLY
1003	}
1004	return openat(dirfd, path, flags, mode)
1005}
1006
1007//sys	openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) = SYS___OPENAT2_A
1008
1009func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) {
1010	if how.Flags&O_ACCMODE == 0 {
1011		how.Flags |= O_RDONLY
1012	}
1013	return openat2(dirfd, path, how, SizeofOpenHow)
1014}
1015
1016func ZosFdToPath(dirfd int) (path string, err error) {
1017	var buffer [1024]byte
1018	runtime.EnterSyscall()
1019	ret, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_W_IOCTL<<4, uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0])))
1020	runtime.ExitSyscall()
1021	if ret == 0 {
1022		zb := bytes.IndexByte(buffer[:], 0)
1023		if zb == -1 {
1024			zb = len(buffer)
1025		}
1026		CallLeFuncWithErr(GetZosLibVec()+SYS___E2A_L<<4, uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb))
1027		return string(buffer[:zb]), nil
1028	}
1029	return "", errnoErr2(e1, e2)
1030}
1031
1032//sys	remove(path string) (err error)
1033
1034func Remove(path string) error {
1035	return remove(path)
1036}
1037
1038const ImplementsGetwd = true
1039
1040func Getcwd(buf []byte) (n int, err error) {
1041	var p unsafe.Pointer
1042	if len(buf) > 0 {
1043		p = unsafe.Pointer(&buf[0])
1044	} else {
1045		p = unsafe.Pointer(&_zero)
1046	}
1047	runtime.EnterSyscall()
1048	r0, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___GETCWD_A<<4, uintptr(p), uintptr(len(buf)))
1049	runtime.ExitSyscall()
1050	n = clen(buf) + 1
1051	if r0 == 0 {
1052		err = errnoErr2(e1, e2)
1053	}
1054	return
1055}
1056
1057func Getwd() (wd string, err error) {
1058	var buf [PathMax]byte
1059	n, err := Getcwd(buf[0:])
1060	if err != nil {
1061		return "", err
1062	}
1063	// Getcwd returns the number of bytes written to buf, including the NUL.
1064	if n < 1 || n > len(buf) || buf[n-1] != 0 {
1065		return "", EINVAL
1066	}
1067	return string(buf[0 : n-1]), nil
1068}
1069
1070func Getgroups() (gids []int, err error) {
1071	n, err := getgroups(0, nil)
1072	if err != nil {
1073		return nil, err
1074	}
1075	if n == 0 {
1076		return nil, nil
1077	}
1078
1079	// Sanity check group count.  Max is 1<<16 on Linux.
1080	if n < 0 || n > 1<<20 {
1081		return nil, EINVAL
1082	}
1083
1084	a := make([]_Gid_t, n)
1085	n, err = getgroups(n, &a[0])
1086	if err != nil {
1087		return nil, err
1088	}
1089	gids = make([]int, n)
1090	for i, v := range a[0:n] {
1091		gids[i] = int(v)
1092	}
1093	return
1094}
1095
1096func Setgroups(gids []int) (err error) {
1097	if len(gids) == 0 {
1098		return setgroups(0, nil)
1099	}
1100
1101	a := make([]_Gid_t, len(gids))
1102	for i, v := range gids {
1103		a[i] = _Gid_t(v)
1104	}
1105	return setgroups(len(a), &a[0])
1106}
1107
1108func gettid() uint64
1109
1110func Gettid() (tid int) {
1111	return int(gettid())
1112}
1113
1114type WaitStatus uint32
1115
1116// Wait status is 7 bits at bottom, either 0 (exited),
1117// 0x7F (stopped), or a signal number that caused an exit.
1118// The 0x80 bit is whether there was a core dump.
1119// An extra number (exit code, signal causing a stop)
1120// is in the high bits.  At least that's the idea.
1121// There are various irregularities.  For example, the
1122// "continued" status is 0xFFFF, distinguishing itself
1123// from stopped via the core dump bit.
1124
1125const (
1126	mask    = 0x7F
1127	core    = 0x80
1128	exited  = 0x00
1129	stopped = 0x7F
1130	shift   = 8
1131)
1132
1133func (w WaitStatus) Exited() bool { return w&mask == exited }
1134
1135func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited }
1136
1137func (w WaitStatus) Stopped() bool { return w&0xFF == stopped }
1138
1139func (w WaitStatus) Continued() bool { return w == 0xFFFF }
1140
1141func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
1142
1143func (w WaitStatus) ExitStatus() int {
1144	if !w.Exited() {
1145		return -1
1146	}
1147	return int(w>>shift) & 0xFF
1148}
1149
1150func (w WaitStatus) Signal() Signal {
1151	if !w.Signaled() {
1152		return -1
1153	}
1154	return Signal(w & mask)
1155}
1156
1157func (w WaitStatus) StopSignal() Signal {
1158	if !w.Stopped() {
1159		return -1
1160	}
1161	return Signal(w>>shift) & 0xFF
1162}
1163
1164func (w WaitStatus) TrapCause() int { return -1 }
1165
1166//sys	waitid(idType int, id int, info *Siginfo, options int) (err error)
1167
1168func Waitid(idType int, id int, info *Siginfo, options int, rusage *Rusage) (err error) {
1169	return waitid(idType, id, info, options)
1170}
1171
1172//sys	waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error)
1173
1174func impl_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
1175	runtime.EnterSyscall()
1176	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAIT4<<4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)))
1177	runtime.ExitSyscall()
1178	wpid = int(r0)
1179	if int64(r0) == -1 {
1180		err = errnoErr2(e1, e2)
1181	}
1182	return
1183}
1184
1185//go:nosplit
1186func get_Wait4Addr() *(func(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error))
1187
1188var Wait4 = enter_Wait4
1189
1190func enter_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
1191	funcref := get_Wait4Addr()
1192	if funcptrtest(GetZosLibVec()+SYS_WAIT4<<4, "") == 0 {
1193		*funcref = impl_Wait4
1194	} else {
1195		*funcref = legacyWait4
1196	}
1197	return (*funcref)(pid, wstatus, options, rusage)
1198}
1199
1200func legacyWait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
1201	// TODO(mundaym): z/OS doesn't have wait4. I don't think getrusage does what we want.
1202	// At the moment rusage will not be touched.
1203	var status _C_int
1204	wpid, err = waitpid(pid, &status, options)
1205	if wstatus != nil {
1206		*wstatus = WaitStatus(status)
1207	}
1208	return
1209}
1210
1211//sysnb	gettimeofday(tv *timeval_zos) (err error)
1212
1213func Gettimeofday(tv *Timeval) (err error) {
1214	var tvz timeval_zos
1215	err = gettimeofday(&tvz)
1216	tv.Sec = tvz.Sec
1217	tv.Usec = int64(tvz.Usec)
1218	return
1219}
1220
1221func Time(t *Time_t) (tt Time_t, err error) {
1222	var tv Timeval
1223	err = Gettimeofday(&tv)
1224	if err != nil {
1225		return 0, err
1226	}
1227	if t != nil {
1228		*t = Time_t(tv.Sec)
1229	}
1230	return Time_t(tv.Sec), nil
1231}
1232
1233func setTimespec(sec, nsec int64) Timespec {
1234	return Timespec{Sec: sec, Nsec: nsec}
1235}
1236
1237func setTimeval(sec, usec int64) Timeval { //fix
1238	return Timeval{Sec: sec, Usec: usec}
1239}
1240
1241//sysnb pipe(p *[2]_C_int) (err error)
1242
1243func Pipe(p []int) (err error) {
1244	if len(p) != 2 {
1245		return EINVAL
1246	}
1247	var pp [2]_C_int
1248	err = pipe(&pp)
1249	p[0] = int(pp[0])
1250	p[1] = int(pp[1])
1251	return
1252}
1253
1254//sys	utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A
1255
1256func Utimes(path string, tv []Timeval) (err error) {
1257	if tv == nil {
1258		return utimes(path, nil)
1259	}
1260	if len(tv) != 2 {
1261		return EINVAL
1262	}
1263	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
1264}
1265
1266//sys	utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) = SYS___UTIMENSAT_A
1267
1268func validUtimensat() bool {
1269	if funcptrtest(GetZosLibVec()+SYS___UTIMENSAT_A<<4, "") == 0 {
1270		if name, err := getLeFuncName(GetZosLibVec() + SYS___UTIMENSAT_A<<4); err == nil {
1271			return name == "__utimensat_a"
1272		}
1273	}
1274	return false
1275}
1276
1277// Begin UtimesNano
1278
1279//go:nosplit
1280func get_UtimesNanoAddr() *(func(path string, ts []Timespec) (err error))
1281
1282var UtimesNano = enter_UtimesNano
1283
1284func enter_UtimesNano(path string, ts []Timespec) (err error) {
1285	funcref := get_UtimesNanoAddr()
1286	if validUtimensat() {
1287		*funcref = utimesNanoImpl
1288	} else {
1289		*funcref = legacyUtimesNano
1290	}
1291	return (*funcref)(path, ts)
1292}
1293
1294func utimesNanoImpl(path string, ts []Timespec) (err error) {
1295	if ts == nil {
1296		return utimensat(AT_FDCWD, path, nil, 0)
1297	}
1298	if len(ts) != 2 {
1299		return EINVAL
1300	}
1301	return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
1302}
1303
1304func legacyUtimesNano(path string, ts []Timespec) (err error) {
1305	if len(ts) != 2 {
1306		return EINVAL
1307	}
1308	// Not as efficient as it could be because Timespec and
1309	// Timeval have different types in the different OSes
1310	tv := [2]Timeval{
1311		NsecToTimeval(TimespecToNsec(ts[0])),
1312		NsecToTimeval(TimespecToNsec(ts[1])),
1313	}
1314	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
1315}
1316
1317// End UtimesNano
1318
1319// Begin UtimesNanoAt
1320
1321//go:nosplit
1322func get_UtimesNanoAtAddr() *(func(dirfd int, path string, ts []Timespec, flags int) (err error))
1323
1324var UtimesNanoAt = enter_UtimesNanoAt
1325
1326func enter_UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) {
1327	funcref := get_UtimesNanoAtAddr()
1328	if validUtimensat() {
1329		*funcref = utimesNanoAtImpl
1330	} else {
1331		*funcref = legacyUtimesNanoAt
1332	}
1333	return (*funcref)(dirfd, path, ts, flags)
1334}
1335
1336func utimesNanoAtImpl(dirfd int, path string, ts []Timespec, flags int) (err error) {
1337	if ts == nil {
1338		return utimensat(dirfd, path, nil, flags)
1339	}
1340	if len(ts) != 2 {
1341		return EINVAL
1342	}
1343	return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
1344}
1345
1346func legacyUtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) {
1347	if path[0] != '/' {
1348		dirPath, err := ZosFdToPath(dirfd)
1349		if err != nil {
1350			return err
1351		}
1352		path = dirPath + "/" + path
1353	}
1354	if flags == AT_SYMLINK_NOFOLLOW {
1355		if len(ts) != 2 {
1356			return EINVAL
1357		}
1358
1359		if ts[0].Nsec >= 5e8 {
1360			ts[0].Sec++
1361		}
1362		ts[0].Nsec = 0
1363		if ts[1].Nsec >= 5e8 {
1364			ts[1].Sec++
1365		}
1366		ts[1].Nsec = 0
1367
1368		// Not as efficient as it could be because Timespec and
1369		// Timeval have different types in the different OSes
1370		tv := []Timeval{
1371			NsecToTimeval(TimespecToNsec(ts[0])),
1372			NsecToTimeval(TimespecToNsec(ts[1])),
1373		}
1374		return Lutimes(path, tv)
1375	}
1376	return UtimesNano(path, ts)
1377}
1378
1379// End UtimesNanoAt
1380
1381func Getsockname(fd int) (sa Sockaddr, err error) {
1382	var rsa RawSockaddrAny
1383	var len _Socklen = SizeofSockaddrAny
1384	if err = getsockname(fd, &rsa, &len); err != nil {
1385		return
1386	}
1387	// TODO(neeilan) : Remove this 0 ( added to get sys/unix compiling on z/OS )
1388	return anyToSockaddr(0, &rsa)
1389}
1390
1391const (
1392	// identifier constants
1393	nwmHeaderIdentifier    = 0xd5e6d4c8
1394	nwmFilterIdentifier    = 0xd5e6d4c6
1395	nwmTCPConnIdentifier   = 0xd5e6d4c3
1396	nwmRecHeaderIdentifier = 0xd5e6d4d9
1397	nwmIPStatsIdentifier   = 0xd5e6d4c9d7e2e340
1398	nwmIPGStatsIdentifier  = 0xd5e6d4c9d7c7e2e3
1399	nwmTCPStatsIdentifier  = 0xd5e6d4e3c3d7e2e3
1400	nwmUDPStatsIdentifier  = 0xd5e6d4e4c4d7e2e3
1401	nwmICMPGStatsEntry     = 0xd5e6d4c9c3d4d7c7
1402	nwmICMPTStatsEntry     = 0xd5e6d4c9c3d4d7e3
1403
1404	// nwmHeader constants
1405	nwmVersion1   = 1
1406	nwmVersion2   = 2
1407	nwmCurrentVer = 2
1408
1409	nwmTCPConnType     = 1
1410	nwmGlobalStatsType = 14
1411
1412	// nwmFilter constants
1413	nwmFilterLclAddrMask = 0x20000000 // Local address
1414	nwmFilterSrcAddrMask = 0x20000000 // Source address
1415	nwmFilterLclPortMask = 0x10000000 // Local port
1416	nwmFilterSrcPortMask = 0x10000000 // Source port
1417
1418	// nwmConnEntry constants
1419	nwmTCPStateClosed   = 1
1420	nwmTCPStateListen   = 2
1421	nwmTCPStateSynSent  = 3
1422	nwmTCPStateSynRcvd  = 4
1423	nwmTCPStateEstab    = 5
1424	nwmTCPStateFinWait1 = 6
1425	nwmTCPStateFinWait2 = 7
1426	nwmTCPStateClosWait = 8
1427	nwmTCPStateLastAck  = 9
1428	nwmTCPStateClosing  = 10
1429	nwmTCPStateTimeWait = 11
1430	nwmTCPStateDeletTCB = 12
1431
1432	// Existing constants on linux
1433	BPF_TCP_CLOSE        = 1
1434	BPF_TCP_LISTEN       = 2
1435	BPF_TCP_SYN_SENT     = 3
1436	BPF_TCP_SYN_RECV     = 4
1437	BPF_TCP_ESTABLISHED  = 5
1438	BPF_TCP_FIN_WAIT1    = 6
1439	BPF_TCP_FIN_WAIT2    = 7
1440	BPF_TCP_CLOSE_WAIT   = 8
1441	BPF_TCP_LAST_ACK     = 9
1442	BPF_TCP_CLOSING      = 10
1443	BPF_TCP_TIME_WAIT    = 11
1444	BPF_TCP_NEW_SYN_RECV = -1
1445	BPF_TCP_MAX_STATES   = -2
1446)
1447
1448type nwmTriplet struct {
1449	offset uint32
1450	length uint32
1451	number uint32
1452}
1453
1454type nwmQuadruplet struct {
1455	offset uint32
1456	length uint32
1457	number uint32
1458	match  uint32
1459}
1460
1461type nwmHeader struct {
1462	ident       uint32
1463	length      uint32
1464	version     uint16
1465	nwmType     uint16
1466	bytesNeeded uint32
1467	options     uint32
1468	_           [16]byte
1469	inputDesc   nwmTriplet
1470	outputDesc  nwmQuadruplet
1471}
1472
1473type nwmFilter struct {
1474	ident         uint32
1475	flags         uint32
1476	resourceName  [8]byte
1477	resourceId    uint32
1478	listenerId    uint32
1479	local         [28]byte // union of sockaddr4 and sockaddr6
1480	remote        [28]byte // union of sockaddr4 and sockaddr6
1481	_             uint16
1482	_             uint16
1483	asid          uint16
1484	_             [2]byte
1485	tnLuName      [8]byte
1486	tnMonGrp      uint32
1487	tnAppl        [8]byte
1488	applData      [40]byte
1489	nInterface    [16]byte
1490	dVipa         [16]byte
1491	dVipaPfx      uint16
1492	dVipaPort     uint16
1493	dVipaFamily   byte
1494	_             [3]byte
1495	destXCF       [16]byte
1496	destXCFPfx    uint16
1497	destXCFFamily byte
1498	_             [1]byte
1499	targIP        [16]byte
1500	targIPPfx     uint16
1501	targIPFamily  byte
1502	_             [1]byte
1503	_             [20]byte
1504}
1505
1506type nwmRecHeader struct {
1507	ident  uint32
1508	length uint32
1509	number byte
1510	_      [3]byte
1511}
1512
1513type nwmTCPStatsEntry struct {
1514	ident             uint64
1515	currEstab         uint32
1516	activeOpened      uint32
1517	passiveOpened     uint32
1518	connClosed        uint32
1519	estabResets       uint32
1520	attemptFails      uint32
1521	passiveDrops      uint32
1522	timeWaitReused    uint32
1523	inSegs            uint64
1524	predictAck        uint32
1525	predictData       uint32
1526	inDupAck          uint32
1527	inBadSum          uint32
1528	inBadLen          uint32
1529	inShort           uint32
1530	inDiscOldTime     uint32
1531	inAllBeforeWin    uint32
1532	inSomeBeforeWin   uint32
1533	inAllAfterWin     uint32
1534	inSomeAfterWin    uint32
1535	inOutOfOrder      uint32
1536	inAfterClose      uint32
1537	inWinProbes       uint32
1538	inWinUpdates      uint32
1539	outWinUpdates     uint32
1540	outSegs           uint64
1541	outDelayAcks      uint32
1542	outRsts           uint32
1543	retransSegs       uint32
1544	retransTimeouts   uint32
1545	retransDrops      uint32
1546	pmtuRetrans       uint32
1547	pmtuErrors        uint32
1548	outWinProbes      uint32
1549	probeDrops        uint32
1550	keepAliveProbes   uint32
1551	keepAliveDrops    uint32
1552	finwait2Drops     uint32
1553	acceptCount       uint64
1554	inBulkQSegs       uint64
1555	inDiscards        uint64
1556	connFloods        uint32
1557	connStalls        uint32
1558	cfgEphemDef       uint16
1559	ephemInUse        uint16
1560	ephemHiWater      uint16
1561	flags             byte
1562	_                 [1]byte
1563	ephemExhaust      uint32
1564	smcRCurrEstabLnks uint32
1565	smcRLnkActTimeOut uint32
1566	smcRActLnkOpened  uint32
1567	smcRPasLnkOpened  uint32
1568	smcRLnksClosed    uint32
1569	smcRCurrEstab     uint32
1570	smcRActiveOpened  uint32
1571	smcRPassiveOpened uint32
1572	smcRConnClosed    uint32
1573	smcRInSegs        uint64
1574	smcROutSegs       uint64
1575	smcRInRsts        uint32
1576	smcROutRsts       uint32
1577	smcDCurrEstabLnks uint32
1578	smcDActLnkOpened  uint32
1579	smcDPasLnkOpened  uint32
1580	smcDLnksClosed    uint32
1581	smcDCurrEstab     uint32
1582	smcDActiveOpened  uint32
1583	smcDPassiveOpened uint32
1584	smcDConnClosed    uint32
1585	smcDInSegs        uint64
1586	smcDOutSegs       uint64
1587	smcDInRsts        uint32
1588	smcDOutRsts       uint32
1589}
1590
1591type nwmConnEntry struct {
1592	ident             uint32
1593	local             [28]byte // union of sockaddr4 and sockaddr6
1594	remote            [28]byte // union of sockaddr4 and sockaddr6
1595	startTime         [8]byte  // uint64, changed to prevent padding from being inserted
1596	lastActivity      [8]byte  // uint64
1597	bytesIn           [8]byte  // uint64
1598	bytesOut          [8]byte  // uint64
1599	inSegs            [8]byte  // uint64
1600	outSegs           [8]byte  // uint64
1601	state             uint16
1602	activeOpen        byte
1603	flag01            byte
1604	outBuffered       uint32
1605	inBuffered        uint32
1606	maxSndWnd         uint32
1607	reXmtCount        uint32
1608	congestionWnd     uint32
1609	ssThresh          uint32
1610	roundTripTime     uint32
1611	roundTripVar      uint32
1612	sendMSS           uint32
1613	sndWnd            uint32
1614	rcvBufSize        uint32
1615	sndBufSize        uint32
1616	outOfOrderCount   uint32
1617	lcl0WindowCount   uint32
1618	rmt0WindowCount   uint32
1619	dupacks           uint32
1620	flag02            byte
1621	sockOpt6Cont      byte
1622	asid              uint16
1623	resourceName      [8]byte
1624	resourceId        uint32
1625	subtask           uint32
1626	sockOpt           byte
1627	sockOpt6          byte
1628	clusterConnFlag   byte
1629	proto             byte
1630	targetAppl        [8]byte
1631	luName            [8]byte
1632	clientUserId      [8]byte
1633	logMode           [8]byte
1634	timeStamp         uint32
1635	timeStampAge      uint32
1636	serverResourceId  uint32
1637	intfName          [16]byte
1638	ttlsStatPol       byte
1639	ttlsStatConn      byte
1640	ttlsSSLProt       uint16
1641	ttlsNegCiph       [2]byte
1642	ttlsSecType       byte
1643	ttlsFIPS140Mode   byte
1644	ttlsUserID        [8]byte
1645	applData          [40]byte
1646	inOldestTime      [8]byte // uint64
1647	outOldestTime     [8]byte // uint64
1648	tcpTrustedPartner byte
1649	_                 [3]byte
1650	bulkDataIntfName  [16]byte
1651	ttlsNegCiph4      [4]byte
1652	smcReason         uint32
1653	lclSMCLinkId      uint32
1654	rmtSMCLinkId      uint32
1655	smcStatus         byte
1656	smcFlags          byte
1657	_                 [2]byte
1658	rcvWnd            uint32
1659	lclSMCBufSz       uint32
1660	rmtSMCBufSz       uint32
1661	ttlsSessID        [32]byte
1662	ttlsSessIDLen     int16
1663	_                 [1]byte
1664	smcDStatus        byte
1665	smcDReason        uint32
1666}
1667
1668var svcNameTable [][]byte = [][]byte{
1669	[]byte("\xc5\xe9\xc2\xd5\xd4\xc9\xc6\xf4"), // svc_EZBNMIF4
1670}
1671
1672const (
1673	svc_EZBNMIF4 = 0
1674)
1675
1676func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) {
1677	jobname := []byte("\x5c\x40\x40\x40\x40\x40\x40\x40") // "*"
1678	responseBuffer := [4096]byte{0}
1679	var bufferAlet, reasonCode uint32 = 0, 0
1680	var bufferLen, returnValue, returnCode int32 = 4096, 0, 0
1681
1682	dsa := [18]uint64{0}
1683	var argv [7]unsafe.Pointer
1684	argv[0] = unsafe.Pointer(&jobname[0])
1685	argv[1] = unsafe.Pointer(&responseBuffer[0])
1686	argv[2] = unsafe.Pointer(&bufferAlet)
1687	argv[3] = unsafe.Pointer(&bufferLen)
1688	argv[4] = unsafe.Pointer(&returnValue)
1689	argv[5] = unsafe.Pointer(&returnCode)
1690	argv[6] = unsafe.Pointer(&reasonCode)
1691
1692	request := (*struct {
1693		header nwmHeader
1694		filter nwmFilter
1695	})(unsafe.Pointer(&responseBuffer[0]))
1696
1697	EZBNMIF4 := svcLoad(&svcNameTable[svc_EZBNMIF4][0])
1698	if EZBNMIF4 == nil {
1699		return nil, errnoErr(EINVAL)
1700	}
1701
1702	// GetGlobalStats EZBNMIF4 call
1703	request.header.ident = nwmHeaderIdentifier
1704	request.header.length = uint32(unsafe.Sizeof(request.header))
1705	request.header.version = nwmCurrentVer
1706	request.header.nwmType = nwmGlobalStatsType
1707	request.header.options = 0x80000000
1708
1709	svcCall(EZBNMIF4, &argv[0], &dsa[0])
1710
1711	// outputDesc field is filled by EZBNMIF4 on success
1712	if returnCode != 0 || request.header.outputDesc.offset == 0 {
1713		return nil, errnoErr(EINVAL)
1714	}
1715
1716	// Check that EZBNMIF4 returned a nwmRecHeader
1717	recHeader := (*nwmRecHeader)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
1718	if recHeader.ident != nwmRecHeaderIdentifier {
1719		return nil, errnoErr(EINVAL)
1720	}
1721
1722	// Parse nwmTriplets to get offsets of returned entries
1723	var sections []*uint64
1724	var sectionDesc *nwmTriplet = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[0]))
1725	for i := uint32(0); i < uint32(recHeader.number); i++ {
1726		offset := request.header.outputDesc.offset + uint32(unsafe.Sizeof(*recHeader)) + i*uint32(unsafe.Sizeof(*sectionDesc))
1727		sectionDesc = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[offset]))
1728		for j := uint32(0); j < sectionDesc.number; j++ {
1729			offset = request.header.outputDesc.offset + sectionDesc.offset + j*sectionDesc.length
1730			sections = append(sections, (*uint64)(unsafe.Pointer(&responseBuffer[offset])))
1731		}
1732	}
1733
1734	// Find nwmTCPStatsEntry in returned entries
1735	var tcpStats *nwmTCPStatsEntry = nil
1736	for _, ptr := range sections {
1737		switch *ptr {
1738		case nwmTCPStatsIdentifier:
1739			if tcpStats != nil {
1740				return nil, errnoErr(EINVAL)
1741			}
1742			tcpStats = (*nwmTCPStatsEntry)(unsafe.Pointer(ptr))
1743		case nwmIPStatsIdentifier:
1744		case nwmIPGStatsIdentifier:
1745		case nwmUDPStatsIdentifier:
1746		case nwmICMPGStatsEntry:
1747		case nwmICMPTStatsEntry:
1748		default:
1749			return nil, errnoErr(EINVAL)
1750		}
1751	}
1752	if tcpStats == nil {
1753		return nil, errnoErr(EINVAL)
1754	}
1755
1756	// GetConnectionDetail EZBNMIF4 call
1757	responseBuffer = [4096]byte{0}
1758	dsa = [18]uint64{0}
1759	bufferAlet, reasonCode = 0, 0
1760	bufferLen, returnValue, returnCode = 4096, 0, 0
1761	nameptr := (*uint32)(unsafe.Pointer(uintptr(0x21c))) // Get jobname of current process
1762	nameptr = (*uint32)(unsafe.Pointer(uintptr(*nameptr + 12)))
1763	argv[0] = unsafe.Pointer(uintptr(*nameptr))
1764
1765	request.header.ident = nwmHeaderIdentifier
1766	request.header.length = uint32(unsafe.Sizeof(request.header))
1767	request.header.version = nwmCurrentVer
1768	request.header.nwmType = nwmTCPConnType
1769	request.header.options = 0x80000000
1770
1771	request.filter.ident = nwmFilterIdentifier
1772
1773	var localSockaddr RawSockaddrAny
1774	socklen := _Socklen(SizeofSockaddrAny)
1775	err := getsockname(fd, &localSockaddr, &socklen)
1776	if err != nil {
1777		return nil, errnoErr(EINVAL)
1778	}
1779	if localSockaddr.Addr.Family == AF_INET {
1780		localSockaddr := (*RawSockaddrInet4)(unsafe.Pointer(&localSockaddr.Addr))
1781		localSockFilter := (*RawSockaddrInet4)(unsafe.Pointer(&request.filter.local[0]))
1782		localSockFilter.Family = AF_INET
1783		var i int
1784		for i = 0; i < 4; i++ {
1785			if localSockaddr.Addr[i] != 0 {
1786				break
1787			}
1788		}
1789		if i != 4 {
1790			request.filter.flags |= nwmFilterLclAddrMask
1791			for i = 0; i < 4; i++ {
1792				localSockFilter.Addr[i] = localSockaddr.Addr[i]
1793			}
1794		}
1795		if localSockaddr.Port != 0 {
1796			request.filter.flags |= nwmFilterLclPortMask
1797			localSockFilter.Port = localSockaddr.Port
1798		}
1799	} else if localSockaddr.Addr.Family == AF_INET6 {
1800		localSockaddr := (*RawSockaddrInet6)(unsafe.Pointer(&localSockaddr.Addr))
1801		localSockFilter := (*RawSockaddrInet6)(unsafe.Pointer(&request.filter.local[0]))
1802		localSockFilter.Family = AF_INET6
1803		var i int
1804		for i = 0; i < 16; i++ {
1805			if localSockaddr.Addr[i] != 0 {
1806				break
1807			}
1808		}
1809		if i != 16 {
1810			request.filter.flags |= nwmFilterLclAddrMask
1811			for i = 0; i < 16; i++ {
1812				localSockFilter.Addr[i] = localSockaddr.Addr[i]
1813			}
1814		}
1815		if localSockaddr.Port != 0 {
1816			request.filter.flags |= nwmFilterLclPortMask
1817			localSockFilter.Port = localSockaddr.Port
1818		}
1819	}
1820
1821	svcCall(EZBNMIF4, &argv[0], &dsa[0])
1822
1823	// outputDesc field is filled by EZBNMIF4 on success
1824	if returnCode != 0 || request.header.outputDesc.offset == 0 {
1825		return nil, errnoErr(EINVAL)
1826	}
1827
1828	// Check that EZBNMIF4 returned a nwmConnEntry
1829	conn := (*nwmConnEntry)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
1830	if conn.ident != nwmTCPConnIdentifier {
1831		return nil, errnoErr(EINVAL)
1832	}
1833
1834	// Copy data from the returned data structures into tcpInfo
1835	// Stats from nwmConnEntry are specific to that connection.
1836	// Stats from nwmTCPStatsEntry are global (to the interface?)
1837	// Fields may not be an exact match. Some fields have no equivalent.
1838	var tcpinfo TCPInfo
1839	tcpinfo.State = uint8(conn.state)
1840	tcpinfo.Ca_state = 0 // dummy
1841	tcpinfo.Retransmits = uint8(tcpStats.retransSegs)
1842	tcpinfo.Probes = uint8(tcpStats.outWinProbes)
1843	tcpinfo.Backoff = 0 // dummy
1844	tcpinfo.Options = 0 // dummy
1845	tcpinfo.Rto = tcpStats.retransTimeouts
1846	tcpinfo.Ato = tcpStats.outDelayAcks
1847	tcpinfo.Snd_mss = conn.sendMSS
1848	tcpinfo.Rcv_mss = conn.sendMSS // dummy
1849	tcpinfo.Unacked = 0            // dummy
1850	tcpinfo.Sacked = 0             // dummy
1851	tcpinfo.Lost = 0               // dummy
1852	tcpinfo.Retrans = conn.reXmtCount
1853	tcpinfo.Fackets = 0 // dummy
1854	tcpinfo.Last_data_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.lastActivity[0])))
1855	tcpinfo.Last_ack_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.outOldestTime[0])))
1856	tcpinfo.Last_data_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
1857	tcpinfo.Last_ack_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
1858	tcpinfo.Pmtu = conn.sendMSS // dummy, NWMIfRouteMtu is a candidate
1859	tcpinfo.Rcv_ssthresh = conn.ssThresh
1860	tcpinfo.Rtt = conn.roundTripTime
1861	tcpinfo.Rttvar = conn.roundTripVar
1862	tcpinfo.Snd_ssthresh = conn.ssThresh // dummy
1863	tcpinfo.Snd_cwnd = conn.congestionWnd
1864	tcpinfo.Advmss = conn.sendMSS        // dummy
1865	tcpinfo.Reordering = 0               // dummy
1866	tcpinfo.Rcv_rtt = conn.roundTripTime // dummy
1867	tcpinfo.Rcv_space = conn.sendMSS     // dummy
1868	tcpinfo.Total_retrans = conn.reXmtCount
1869
1870	svcUnload(&svcNameTable[svc_EZBNMIF4][0], EZBNMIF4)
1871
1872	return &tcpinfo, nil
1873}
1874
1875// GetsockoptString returns the string value of the socket option opt for the
1876// socket associated with fd at the given socket level.
1877func GetsockoptString(fd, level, opt int) (string, error) {
1878	buf := make([]byte, 256)
1879	vallen := _Socklen(len(buf))
1880	err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
1881	if err != nil {
1882		return "", err
1883	}
1884
1885	return ByteSliceToString(buf[:vallen]), nil
1886}
1887
1888func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
1889	var msg Msghdr
1890	var rsa RawSockaddrAny
1891	msg.Name = (*byte)(unsafe.Pointer(&rsa))
1892	msg.Namelen = SizeofSockaddrAny
1893	var iov Iovec
1894	if len(p) > 0 {
1895		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
1896		iov.SetLen(len(p))
1897	}
1898	var dummy byte
1899	if len(oob) > 0 {
1900		// receive at least one normal byte
1901		if len(p) == 0 {
1902			iov.Base = &dummy
1903			iov.SetLen(1)
1904		}
1905		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
1906		msg.SetControllen(len(oob))
1907	}
1908	msg.Iov = &iov
1909	msg.Iovlen = 1
1910	if n, err = recvmsg(fd, &msg, flags); err != nil {
1911		return
1912	}
1913	oobn = int(msg.Controllen)
1914	recvflags = int(msg.Flags)
1915	// source address is only specified if the socket is unconnected
1916	if rsa.Addr.Family != AF_UNSPEC {
1917		// TODO(neeilan): Remove 0 arg added to get this compiling on z/OS
1918		from, err = anyToSockaddr(0, &rsa)
1919	}
1920	return
1921}
1922
1923func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
1924	_, err = SendmsgN(fd, p, oob, to, flags)
1925	return
1926}
1927
1928func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
1929	var ptr unsafe.Pointer
1930	var salen _Socklen
1931	if to != nil {
1932		var err error
1933		ptr, salen, err = to.sockaddr()
1934		if err != nil {
1935			return 0, err
1936		}
1937	}
1938	var msg Msghdr
1939	msg.Name = (*byte)(unsafe.Pointer(ptr))
1940	msg.Namelen = int32(salen)
1941	var iov Iovec
1942	if len(p) > 0 {
1943		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
1944		iov.SetLen(len(p))
1945	}
1946	var dummy byte
1947	if len(oob) > 0 {
1948		// send at least one normal byte
1949		if len(p) == 0 {
1950			iov.Base = &dummy
1951			iov.SetLen(1)
1952		}
1953		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
1954		msg.SetControllen(len(oob))
1955	}
1956	msg.Iov = &iov
1957	msg.Iovlen = 1
1958	if n, err = sendmsg(fd, &msg, flags); err != nil {
1959		return 0, err
1960	}
1961	if len(oob) > 0 && len(p) == 0 {
1962		n = 0
1963	}
1964	return n, nil
1965}
1966
1967func Opendir(name string) (uintptr, error) {
1968	p, err := BytePtrFromString(name)
1969	if err != nil {
1970		return 0, err
1971	}
1972	err = nil
1973	runtime.EnterSyscall()
1974	dir, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___OPENDIR_A<<4, uintptr(unsafe.Pointer(p)))
1975	runtime.ExitSyscall()
1976	runtime.KeepAlive(unsafe.Pointer(p))
1977	if dir == 0 {
1978		err = errnoErr2(e1, e2)
1979	}
1980	return dir, err
1981}
1982
1983// clearsyscall.Errno resets the errno value to 0.
1984func clearErrno()
1985
1986func Closedir(dir uintptr) error {
1987	runtime.EnterSyscall()
1988	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSEDIR<<4, dir)
1989	runtime.ExitSyscall()
1990	if r0 != 0 {
1991		return errnoErr2(e1, e2)
1992	}
1993	return nil
1994}
1995
1996func Seekdir(dir uintptr, pos int) {
1997	runtime.EnterSyscall()
1998	CallLeFuncWithErr(GetZosLibVec()+SYS_SEEKDIR<<4, dir, uintptr(pos))
1999	runtime.ExitSyscall()
2000}
2001
2002func Telldir(dir uintptr) (int, error) {
2003	p, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TELLDIR<<4, dir)
2004	pos := int(p)
2005	if int64(p) == -1 {
2006		return pos, errnoErr2(e1, e2)
2007	}
2008	return pos, nil
2009}
2010
2011// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
2012func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
2013	// struct flock is packed on z/OS. We can't emulate that in Go so
2014	// instead we pack it here.
2015	var flock [24]byte
2016	*(*int16)(unsafe.Pointer(&flock[0])) = lk.Type
2017	*(*int16)(unsafe.Pointer(&flock[2])) = lk.Whence
2018	*(*int64)(unsafe.Pointer(&flock[4])) = lk.Start
2019	*(*int64)(unsafe.Pointer(&flock[12])) = lk.Len
2020	*(*int32)(unsafe.Pointer(&flock[20])) = lk.Pid
2021	runtime.EnterSyscall()
2022	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock)))
2023	runtime.ExitSyscall()
2024	lk.Type = *(*int16)(unsafe.Pointer(&flock[0]))
2025	lk.Whence = *(*int16)(unsafe.Pointer(&flock[2]))
2026	lk.Start = *(*int64)(unsafe.Pointer(&flock[4]))
2027	lk.Len = *(*int64)(unsafe.Pointer(&flock[12]))
2028	lk.Pid = *(*int32)(unsafe.Pointer(&flock[20]))
2029	if r0 == 0 {
2030		return nil
2031	}
2032	return errnoErr2(e1, e2)
2033}
2034
2035func impl_Flock(fd int, how int) (err error) {
2036	runtime.EnterSyscall()
2037	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FLOCK<<4, uintptr(fd), uintptr(how))
2038	runtime.ExitSyscall()
2039	if int64(r0) == -1 {
2040		err = errnoErr2(e1, e2)
2041	}
2042	return
2043}
2044
2045//go:nosplit
2046func get_FlockAddr() *(func(fd int, how int) (err error))
2047
2048var Flock = enter_Flock
2049
2050func validFlock(fp uintptr) bool {
2051	if funcptrtest(GetZosLibVec()+SYS_FLOCK<<4, "") == 0 {
2052		if name, err := getLeFuncName(GetZosLibVec() + SYS_FLOCK<<4); err == nil {
2053			return name == "flock"
2054		}
2055	}
2056	return false
2057}
2058
2059func enter_Flock(fd int, how int) (err error) {
2060	funcref := get_FlockAddr()
2061	if validFlock(GetZosLibVec() + SYS_FLOCK<<4) {
2062		*funcref = impl_Flock
2063	} else {
2064		*funcref = legacyFlock
2065	}
2066	return (*funcref)(fd, how)
2067}
2068
2069func legacyFlock(fd int, how int) error {
2070
2071	var flock_type int16
2072	var fcntl_cmd int
2073
2074	switch how {
2075	case LOCK_SH | LOCK_NB:
2076		flock_type = F_RDLCK
2077		fcntl_cmd = F_SETLK
2078	case LOCK_EX | LOCK_NB:
2079		flock_type = F_WRLCK
2080		fcntl_cmd = F_SETLK
2081	case LOCK_EX:
2082		flock_type = F_WRLCK
2083		fcntl_cmd = F_SETLKW
2084	case LOCK_UN:
2085		flock_type = F_UNLCK
2086		fcntl_cmd = F_SETLKW
2087	default:
2088	}
2089
2090	flock := Flock_t{
2091		Type:   int16(flock_type),
2092		Whence: int16(0),
2093		Start:  int64(0),
2094		Len:    int64(0),
2095		Pid:    int32(Getppid()),
2096	}
2097
2098	err := FcntlFlock(uintptr(fd), fcntl_cmd, &flock)
2099	return err
2100}
2101
2102func Mlock(b []byte) (err error) {
2103	runtime.EnterSyscall()
2104	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP)
2105	runtime.ExitSyscall()
2106	if r0 != 0 {
2107		err = errnoErr2(e1, e2)
2108	}
2109	return
2110}
2111
2112func Mlock2(b []byte, flags int) (err error) {
2113	runtime.EnterSyscall()
2114	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP)
2115	runtime.ExitSyscall()
2116	if r0 != 0 {
2117		err = errnoErr2(e1, e2)
2118	}
2119	return
2120}
2121
2122func Mlockall(flags int) (err error) {
2123	runtime.EnterSyscall()
2124	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP)
2125	runtime.ExitSyscall()
2126	if r0 != 0 {
2127		err = errnoErr2(e1, e2)
2128	}
2129	return
2130}
2131
2132func Munlock(b []byte) (err error) {
2133	runtime.EnterSyscall()
2134	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP)
2135	runtime.ExitSyscall()
2136	if r0 != 0 {
2137		err = errnoErr2(e1, e2)
2138	}
2139	return
2140}
2141
2142func Munlockall() (err error) {
2143	runtime.EnterSyscall()
2144	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP)
2145	runtime.ExitSyscall()
2146	if r0 != 0 {
2147		err = errnoErr2(e1, e2)
2148	}
2149	return
2150}
2151
2152func ClockGettime(clockid int32, ts *Timespec) error {
2153
2154	var ticks_per_sec uint32 = 100 //TODO(kenan): value is currently hardcoded; need sysconf() call otherwise
2155	var nsec_per_sec int64 = 1000000000
2156
2157	if ts == nil {
2158		return EFAULT
2159	}
2160	if clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC {
2161		var nanotime int64 = runtime.Nanotime1()
2162		ts.Sec = nanotime / nsec_per_sec
2163		ts.Nsec = nanotime % nsec_per_sec
2164	} else if clockid == CLOCK_PROCESS_CPUTIME_ID || clockid == CLOCK_THREAD_CPUTIME_ID {
2165		var tm Tms
2166		_, err := Times(&tm)
2167		if err != nil {
2168			return EFAULT
2169		}
2170		ts.Sec = int64(tm.Utime / ticks_per_sec)
2171		ts.Nsec = int64(tm.Utime) * nsec_per_sec / int64(ticks_per_sec)
2172	} else {
2173		return EINVAL
2174	}
2175	return nil
2176}
2177
2178// Chtag
2179
2180//go:nosplit
2181func get_ChtagAddr() *(func(path string, ccsid uint64, textbit uint64) error)
2182
2183var Chtag = enter_Chtag
2184
2185func enter_Chtag(path string, ccsid uint64, textbit uint64) error {
2186	funcref := get_ChtagAddr()
2187	if validSetxattr() {
2188		*funcref = impl_Chtag
2189	} else {
2190		*funcref = legacy_Chtag
2191	}
2192	return (*funcref)(path, ccsid, textbit)
2193}
2194
2195func legacy_Chtag(path string, ccsid uint64, textbit uint64) error {
2196	tag := ccsid<<16 | textbit<<15
2197	var tag_buff [8]byte
2198	DecodeData(tag_buff[:], 8, tag)
2199	return Setxattr(path, "filetag", tag_buff[:], XATTR_REPLACE)
2200}
2201
2202func impl_Chtag(path string, ccsid uint64, textbit uint64) error {
2203	tag := ccsid<<16 | textbit<<15
2204	var tag_buff [4]byte
2205	DecodeData(tag_buff[:], 4, tag)
2206	return Setxattr(path, "system.filetag", tag_buff[:], XATTR_REPLACE)
2207}
2208
2209// End of Chtag
2210
2211// Nanosleep
2212
2213//go:nosplit
2214func get_NanosleepAddr() *(func(time *Timespec, leftover *Timespec) error)
2215
2216var Nanosleep = enter_Nanosleep
2217
2218func enter_Nanosleep(time *Timespec, leftover *Timespec) error {
2219	funcref := get_NanosleepAddr()
2220	if funcptrtest(GetZosLibVec()+SYS_NANOSLEEP<<4, "") == 0 {
2221		*funcref = impl_Nanosleep
2222	} else {
2223		*funcref = legacyNanosleep
2224	}
2225	return (*funcref)(time, leftover)
2226}
2227
2228func impl_Nanosleep(time *Timespec, leftover *Timespec) error {
2229	runtime.EnterSyscall()
2230	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_NANOSLEEP<<4, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)))
2231	runtime.ExitSyscall()
2232	if int64(r0) == -1 {
2233		return errnoErr2(e1, e2)
2234	}
2235	return nil
2236}
2237
2238func legacyNanosleep(time *Timespec, leftover *Timespec) error {
2239	t0 := runtime.Nanotime1()
2240	var secrem uint32
2241	var nsecrem uint32
2242	total := time.Sec*1000000000 + time.Nsec
2243	elapsed := runtime.Nanotime1() - t0
2244	var rv int32
2245	var rc int32
2246	var err error
2247	// repeatedly sleep for 1 second until less than 1 second left
2248	for total-elapsed > 1000000000 {
2249		rv, rc, _ = BpxCondTimedWait(uint32(1), uint32(0), uint32(CW_CONDVAR), &secrem, &nsecrem)
2250		if rv != 0 && rc != 112 { // 112 is EAGAIN
2251			if leftover != nil && rc == 120 { // 120 is EINTR
2252				leftover.Sec = int64(secrem)
2253				leftover.Nsec = int64(nsecrem)
2254			}
2255			err = Errno(rc)
2256			return err
2257		}
2258		elapsed = runtime.Nanotime1() - t0
2259	}
2260	// sleep the remainder
2261	if total > elapsed {
2262		rv, rc, _ = BpxCondTimedWait(uint32(0), uint32(total-elapsed), uint32(CW_CONDVAR), &secrem, &nsecrem)
2263	}
2264	if leftover != nil && rc == 120 {
2265		leftover.Sec = int64(secrem)
2266		leftover.Nsec = int64(nsecrem)
2267	}
2268	if rv != 0 && rc != 112 {
2269		err = Errno(rc)
2270	}
2271	return err
2272}
2273
2274// End of Nanosleep
2275
2276var (
2277	Stdin  = 0
2278	Stdout = 1
2279	Stderr = 2
2280)
2281
2282// Do the interface allocations only once for common
2283// Errno values.
2284var (
2285	errEAGAIN error = syscall.EAGAIN
2286	errEINVAL error = syscall.EINVAL
2287	errENOENT error = syscall.ENOENT
2288)
2289
2290var ZosTraceLevel int
2291var ZosTracefile *os.File
2292
2293var (
2294	signalNameMapOnce sync.Once
2295	signalNameMap     map[string]syscall.Signal
2296)
2297
2298// errnoErr returns common boxed Errno values, to prevent
2299// allocations at runtime.
2300func errnoErr(e Errno) error {
2301	switch e {
2302	case 0:
2303		return nil
2304	case EAGAIN:
2305		return errEAGAIN
2306	case EINVAL:
2307		return errEINVAL
2308	case ENOENT:
2309		return errENOENT
2310	}
2311	return e
2312}
2313
2314var reg *regexp.Regexp
2315
2316// enhanced with zos specific errno2
2317func errnoErr2(e Errno, e2 uintptr) error {
2318	switch e {
2319	case 0:
2320		return nil
2321	case EAGAIN:
2322		return errEAGAIN
2323		/*
2324			Allow the retrieval of errno2 for EINVAL and ENOENT on zos
2325				case EINVAL:
2326					return errEINVAL
2327				case ENOENT:
2328					return errENOENT
2329		*/
2330	}
2331	if ZosTraceLevel > 0 {
2332		var name string
2333		if reg == nil {
2334			reg = regexp.MustCompile("(^unix\\.[^/]+$|.*\\/unix\\.[^/]+$)")
2335		}
2336		i := 1
2337		pc, file, line, ok := runtime.Caller(i)
2338		if ok {
2339			name = runtime.FuncForPC(pc).Name()
2340		}
2341		for ok && reg.MatchString(runtime.FuncForPC(pc).Name()) {
2342			i += 1
2343			pc, file, line, ok = runtime.Caller(i)
2344		}
2345		if ok {
2346			if ZosTracefile == nil {
2347				ZosConsolePrintf("From %s:%d\n", file, line)
2348				ZosConsolePrintf("%s: %s (errno2=0x%x)\n", name, e.Error(), e2)
2349			} else {
2350				fmt.Fprintf(ZosTracefile, "From %s:%d\n", file, line)
2351				fmt.Fprintf(ZosTracefile, "%s: %s (errno2=0x%x)\n", name, e.Error(), e2)
2352			}
2353		} else {
2354			if ZosTracefile == nil {
2355				ZosConsolePrintf("%s (errno2=0x%x)\n", e.Error(), e2)
2356			} else {
2357				fmt.Fprintf(ZosTracefile, "%s (errno2=0x%x)\n", e.Error(), e2)
2358			}
2359		}
2360	}
2361	return e
2362}
2363
2364// ErrnoName returns the error name for error number e.
2365func ErrnoName(e Errno) string {
2366	i := sort.Search(len(errorList), func(i int) bool {
2367		return errorList[i].num >= e
2368	})
2369	if i < len(errorList) && errorList[i].num == e {
2370		return errorList[i].name
2371	}
2372	return ""
2373}
2374
2375// SignalName returns the signal name for signal number s.
2376func SignalName(s syscall.Signal) string {
2377	i := sort.Search(len(signalList), func(i int) bool {
2378		return signalList[i].num >= s
2379	})
2380	if i < len(signalList) && signalList[i].num == s {
2381		return signalList[i].name
2382	}
2383	return ""
2384}
2385
2386// SignalNum returns the syscall.Signal for signal named s,
2387// or 0 if a signal with such name is not found.
2388// The signal name should start with "SIG".
2389func SignalNum(s string) syscall.Signal {
2390	signalNameMapOnce.Do(func() {
2391		signalNameMap = make(map[string]syscall.Signal, len(signalList))
2392		for _, signal := range signalList {
2393			signalNameMap[signal.name] = signal.num
2394		}
2395	})
2396	return signalNameMap[s]
2397}
2398
2399// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
2400func clen(n []byte) int {
2401	i := bytes.IndexByte(n, 0)
2402	if i == -1 {
2403		i = len(n)
2404	}
2405	return i
2406}
2407
2408// Mmap manager, for use by operating system-specific implementations.
2409
2410type mmapper struct {
2411	sync.Mutex
2412	active map[*byte][]byte // active mappings; key is last byte in mapping
2413	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
2414	munmap func(addr uintptr, length uintptr) error
2415}
2416
2417func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
2418	if length <= 0 {
2419		return nil, EINVAL
2420	}
2421
2422	// Set __MAP_64 by default
2423	flags |= __MAP_64
2424
2425	// Map the requested memory.
2426	addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
2427	if errno != nil {
2428		return nil, errno
2429	}
2430
2431	// Slice memory layout
2432	var sl = struct {
2433		addr uintptr
2434		len  int
2435		cap  int
2436	}{addr, length, length}
2437
2438	// Use unsafe to turn sl into a []byte.
2439	b := *(*[]byte)(unsafe.Pointer(&sl))
2440
2441	// Register mapping in m and return it.
2442	p := &b[cap(b)-1]
2443	m.Lock()
2444	defer m.Unlock()
2445	m.active[p] = b
2446	return b, nil
2447}
2448
2449func (m *mmapper) Munmap(data []byte) (err error) {
2450	if len(data) == 0 || len(data) != cap(data) {
2451		return EINVAL
2452	}
2453
2454	// Find the base of the mapping.
2455	p := &data[cap(data)-1]
2456	m.Lock()
2457	defer m.Unlock()
2458	b := m.active[p]
2459	if b == nil || &b[0] != &data[0] {
2460		return EINVAL
2461	}
2462
2463	// Unmap the memory and update m.
2464	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
2465		return errno
2466	}
2467	delete(m.active, p)
2468	return nil
2469}
2470
2471func Read(fd int, p []byte) (n int, err error) {
2472	n, err = read(fd, p)
2473	if raceenabled {
2474		if n > 0 {
2475			raceWriteRange(unsafe.Pointer(&p[0]), n)
2476		}
2477		if err == nil {
2478			raceAcquire(unsafe.Pointer(&ioSync))
2479		}
2480	}
2481	return
2482}
2483
2484func Write(fd int, p []byte) (n int, err error) {
2485	if raceenabled {
2486		raceReleaseMerge(unsafe.Pointer(&ioSync))
2487	}
2488	n, err = write(fd, p)
2489	if raceenabled && n > 0 {
2490		raceReadRange(unsafe.Pointer(&p[0]), n)
2491	}
2492	return
2493}
2494
2495// For testing: clients can set this flag to force
2496// creation of IPv6 sockets to return EAFNOSUPPORT.
2497var SocketDisableIPv6 bool
2498
2499// Sockaddr represents a socket address.
2500type Sockaddr interface {
2501	sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs
2502}
2503
2504// SockaddrInet4 implements the Sockaddr interface for AF_INET type sockets.
2505type SockaddrInet4 struct {
2506	Port int
2507	Addr [4]byte
2508	raw  RawSockaddrInet4
2509}
2510
2511// SockaddrInet6 implements the Sockaddr interface for AF_INET6 type sockets.
2512type SockaddrInet6 struct {
2513	Port   int
2514	ZoneId uint32
2515	Addr   [16]byte
2516	raw    RawSockaddrInet6
2517}
2518
2519// SockaddrUnix implements the Sockaddr interface for AF_UNIX type sockets.
2520type SockaddrUnix struct {
2521	Name string
2522	raw  RawSockaddrUnix
2523}
2524
2525func Bind(fd int, sa Sockaddr) (err error) {
2526	ptr, n, err := sa.sockaddr()
2527	if err != nil {
2528		return err
2529	}
2530	return bind(fd, ptr, n)
2531}
2532
2533func Connect(fd int, sa Sockaddr) (err error) {
2534	ptr, n, err := sa.sockaddr()
2535	if err != nil {
2536		return err
2537	}
2538	return connect(fd, ptr, n)
2539}
2540
2541func Getpeername(fd int) (sa Sockaddr, err error) {
2542	var rsa RawSockaddrAny
2543	var len _Socklen = SizeofSockaddrAny
2544	if err = getpeername(fd, &rsa, &len); err != nil {
2545		return
2546	}
2547	return anyToSockaddr(fd, &rsa)
2548}
2549
2550func GetsockoptByte(fd, level, opt int) (value byte, err error) {
2551	var n byte
2552	vallen := _Socklen(1)
2553	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
2554	return n, err
2555}
2556
2557func GetsockoptInt(fd, level, opt int) (value int, err error) {
2558	var n int32
2559	vallen := _Socklen(4)
2560	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
2561	return int(n), err
2562}
2563
2564func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
2565	vallen := _Socklen(4)
2566	err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
2567	return value, err
2568}
2569
2570func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
2571	var value IPMreq
2572	vallen := _Socklen(SizeofIPMreq)
2573	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
2574	return &value, err
2575}
2576
2577func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
2578	var value IPv6Mreq
2579	vallen := _Socklen(SizeofIPv6Mreq)
2580	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
2581	return &value, err
2582}
2583
2584func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) {
2585	var value IPv6MTUInfo
2586	vallen := _Socklen(SizeofIPv6MTUInfo)
2587	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
2588	return &value, err
2589}
2590
2591func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {
2592	var value ICMPv6Filter
2593	vallen := _Socklen(SizeofICMPv6Filter)
2594	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
2595	return &value, err
2596}
2597
2598func GetsockoptLinger(fd, level, opt int) (*Linger, error) {
2599	var linger Linger
2600	vallen := _Socklen(SizeofLinger)
2601	err := getsockopt(fd, level, opt, unsafe.Pointer(&linger), &vallen)
2602	return &linger, err
2603}
2604
2605func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) {
2606	var tv Timeval
2607	vallen := _Socklen(unsafe.Sizeof(tv))
2608	err := getsockopt(fd, level, opt, unsafe.Pointer(&tv), &vallen)
2609	return &tv, err
2610}
2611
2612func GetsockoptUint64(fd, level, opt int) (value uint64, err error) {
2613	var n uint64
2614	vallen := _Socklen(8)
2615	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
2616	return n, err
2617}
2618
2619func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
2620	var rsa RawSockaddrAny
2621	var len _Socklen = SizeofSockaddrAny
2622	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
2623		return
2624	}
2625	if rsa.Addr.Family != AF_UNSPEC {
2626		from, err = anyToSockaddr(fd, &rsa)
2627	}
2628	return
2629}
2630
2631func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
2632	ptr, n, err := to.sockaddr()
2633	if err != nil {
2634		return err
2635	}
2636	return sendto(fd, p, flags, ptr, n)
2637}
2638
2639func SetsockoptByte(fd, level, opt int, value byte) (err error) {
2640	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
2641}
2642
2643func SetsockoptInt(fd, level, opt int, value int) (err error) {
2644	var n = int32(value)
2645	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
2646}
2647
2648func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
2649	return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
2650}
2651
2652func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
2653	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq)
2654}
2655
2656func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
2657	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq)
2658}
2659
2660func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
2661	return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
2662}
2663
2664func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
2665	return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger)
2666}
2667
2668func SetsockoptString(fd, level, opt int, s string) (err error) {
2669	var p unsafe.Pointer
2670	if len(s) > 0 {
2671		p = unsafe.Pointer(&[]byte(s)[0])
2672	}
2673	return setsockopt(fd, level, opt, p, uintptr(len(s)))
2674}
2675
2676func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
2677	return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv))
2678}
2679
2680func SetsockoptUint64(fd, level, opt int, value uint64) (err error) {
2681	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 8)
2682}
2683
2684func Socket(domain, typ, proto int) (fd int, err error) {
2685	if domain == AF_INET6 && SocketDisableIPv6 {
2686		return -1, EAFNOSUPPORT
2687	}
2688	fd, err = socket(domain, typ, proto)
2689	return
2690}
2691
2692func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
2693	var fdx [2]int32
2694	err = socketpair(domain, typ, proto, &fdx)
2695	if err == nil {
2696		fd[0] = int(fdx[0])
2697		fd[1] = int(fdx[1])
2698	}
2699	return
2700}
2701
2702var ioSync int64
2703
2704func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
2705
2706func SetNonblock(fd int, nonblocking bool) (err error) {
2707	flag, err := fcntl(fd, F_GETFL, 0)
2708	if err != nil {
2709		return err
2710	}
2711	if nonblocking {
2712		flag |= O_NONBLOCK
2713	} else {
2714		flag &= ^O_NONBLOCK
2715	}
2716	_, err = fcntl(fd, F_SETFL, flag)
2717	return err
2718}
2719
2720// Exec calls execve(2), which replaces the calling executable in the process
2721// tree. argv0 should be the full path to an executable ("/bin/ls") and the
2722// executable name should also be the first argument in argv (["ls", "-l"]).
2723// envv are the environment variables that should be passed to the new
2724// process (["USER=go", "PWD=/tmp"]).
2725func Exec(argv0 string, argv []string, envv []string) error {
2726	return syscall.Exec(argv0, argv, envv)
2727}
2728
2729func Getag(path string) (ccsid uint16, flag uint16, err error) {
2730	var val [8]byte
2731	sz, err := Getxattr(path, "ccsid", val[:])
2732	if err != nil {
2733		return
2734	}
2735	ccsid = uint16(EncodeData(val[0:sz]))
2736	sz, err = Getxattr(path, "flags", val[:])
2737	if err != nil {
2738		return
2739	}
2740	flag = uint16(EncodeData(val[0:sz]) >> 15)
2741	return
2742}
2743
2744// Mount begin
2745func impl_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
2746	var _p0 *byte
2747	_p0, err = BytePtrFromString(source)
2748	if err != nil {
2749		return
2750	}
2751	var _p1 *byte
2752	_p1, err = BytePtrFromString(target)
2753	if err != nil {
2754		return
2755	}
2756	var _p2 *byte
2757	_p2, err = BytePtrFromString(fstype)
2758	if err != nil {
2759		return
2760	}
2761	var _p3 *byte
2762	_p3, err = BytePtrFromString(data)
2763	if err != nil {
2764		return
2765	}
2766	runtime.EnterSyscall()
2767	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)))
2768	runtime.ExitSyscall()
2769	if int64(r0) == -1 {
2770		err = errnoErr2(e1, e2)
2771	}
2772	return
2773}
2774
2775//go:nosplit
2776func get_MountAddr() *(func(source string, target string, fstype string, flags uintptr, data string) (err error))
2777
2778var Mount = enter_Mount
2779
2780func enter_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
2781	funcref := get_MountAddr()
2782	if validMount() {
2783		*funcref = impl_Mount
2784	} else {
2785		*funcref = legacyMount
2786	}
2787	return (*funcref)(source, target, fstype, flags, data)
2788}
2789
2790func legacyMount(source string, target string, fstype string, flags uintptr, data string) (err error) {
2791	if needspace := 8 - len(fstype); needspace <= 0 {
2792		fstype = fstype[0:8]
2793	} else {
2794		fstype += "        "[0:needspace]
2795	}
2796	return mount_LE(target, source, fstype, uint32(flags), int32(len(data)), data)
2797}
2798
2799func validMount() bool {
2800	if funcptrtest(GetZosLibVec()+SYS___MOUNT1_A<<4, "") == 0 {
2801		if name, err := getLeFuncName(GetZosLibVec() + SYS___MOUNT1_A<<4); err == nil {
2802			return name == "__mount1_a"
2803		}
2804	}
2805	return false
2806}
2807
2808// Mount end
2809
2810// Unmount begin
2811func impl_Unmount(target string, flags int) (err error) {
2812	var _p0 *byte
2813	_p0, err = BytePtrFromString(target)
2814	if err != nil {
2815		return
2816	}
2817	runtime.EnterSyscall()
2818	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UMOUNT2_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(flags))
2819	runtime.ExitSyscall()
2820	if int64(r0) == -1 {
2821		err = errnoErr2(e1, e2)
2822	}
2823	return
2824}
2825
2826//go:nosplit
2827func get_UnmountAddr() *(func(target string, flags int) (err error))
2828
2829var Unmount = enter_Unmount
2830
2831func enter_Unmount(target string, flags int) (err error) {
2832	funcref := get_UnmountAddr()
2833	if funcptrtest(GetZosLibVec()+SYS___UMOUNT2_A<<4, "") == 0 {
2834		*funcref = impl_Unmount
2835	} else {
2836		*funcref = legacyUnmount
2837	}
2838	return (*funcref)(target, flags)
2839}
2840
2841func legacyUnmount(name string, mtm int) (err error) {
2842	// mountpoint is always a full path and starts with a '/'
2843	// check if input string is not a mountpoint but a filesystem name
2844	if name[0] != '/' {
2845		return unmount_LE(name, mtm)
2846	}
2847	// treat name as mountpoint
2848	b2s := func(arr []byte) string {
2849		var str string
2850		for i := 0; i < len(arr); i++ {
2851			if arr[i] == 0 {
2852				str = string(arr[:i])
2853				break
2854			}
2855		}
2856		return str
2857	}
2858	var buffer struct {
2859		header W_Mnth
2860		fsinfo [64]W_Mntent
2861	}
2862	fs_count, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer)))
2863	if err == nil {
2864		err = EINVAL
2865		for i := 0; i < fs_count; i++ {
2866			if b2s(buffer.fsinfo[i].Mountpoint[:]) == name {
2867				err = unmount_LE(b2s(buffer.fsinfo[i].Fsname[:]), mtm)
2868				break
2869			}
2870		}
2871	} else if fs_count == 0 {
2872		err = EINVAL
2873	}
2874	return err
2875}
2876
2877// Unmount end
2878
2879func direntIno(buf []byte) (uint64, bool) {
2880	return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
2881}
2882
2883func direntReclen(buf []byte) (uint64, bool) {
2884	return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
2885}
2886
2887func direntNamlen(buf []byte) (uint64, bool) {
2888	reclen, ok := direntReclen(buf)
2889	if !ok {
2890		return 0, false
2891	}
2892	return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
2893}
2894
2895func direntLeToDirentUnix(dirent *direntLE, dir uintptr, path string) (Dirent, error) {
2896	var d Dirent
2897
2898	d.Ino = uint64(dirent.Ino)
2899	offset, err := Telldir(dir)
2900	if err != nil {
2901		return d, err
2902	}
2903
2904	d.Off = int64(offset)
2905	s := string(bytes.Split(dirent.Name[:], []byte{0})[0])
2906	copy(d.Name[:], s)
2907
2908	d.Reclen = uint16(24 + len(d.NameString()))
2909	var st Stat_t
2910	path = path + "/" + s
2911	err = Lstat(path, &st)
2912	if err != nil {
2913		return d, err
2914	}
2915
2916	d.Type = uint8(st.Mode >> 24)
2917	return d, err
2918}
2919
2920func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
2921	// Simulation of Getdirentries port from the Darwin implementation.
2922	// COMMENTS FROM DARWIN:
2923	// It's not the full required semantics, but should handle the case
2924	// of calling Getdirentries or ReadDirent repeatedly.
2925	// It won't handle assigning the results of lseek to *basep, or handle
2926	// the directory being edited underfoot.
2927
2928	skip, err := Seek(fd, 0, 1 /* SEEK_CUR */)
2929	if err != nil {
2930		return 0, err
2931	}
2932
2933	// Get path from fd to avoid unavailable call (fdopendir)
2934	path, err := ZosFdToPath(fd)
2935	if err != nil {
2936		return 0, err
2937	}
2938	d, err := Opendir(path)
2939	if err != nil {
2940		return 0, err
2941	}
2942	defer Closedir(d)
2943
2944	var cnt int64
2945	for {
2946		var entryLE direntLE
2947		var entrypLE *direntLE
2948		e := Readdir_r(d, &entryLE, &entrypLE)
2949		if e != nil {
2950			return n, e
2951		}
2952		if entrypLE == nil {
2953			break
2954		}
2955		if skip > 0 {
2956			skip--
2957			cnt++
2958			continue
2959		}
2960
2961		// Dirent on zos has a different structure
2962		entry, e := direntLeToDirentUnix(&entryLE, d, path)
2963		if e != nil {
2964			return n, e
2965		}
2966
2967		reclen := int(entry.Reclen)
2968		if reclen > len(buf) {
2969			// Not enough room. Return for now.
2970			// The counter will let us know where we should start up again.
2971			// Note: this strategy for suspending in the middle and
2972			// restarting is O(n^2) in the length of the directory. Oh well.
2973			break
2974		}
2975
2976		// Copy entry into return buffer.
2977		s := unsafe.Slice((*byte)(unsafe.Pointer(&entry)), reclen)
2978		copy(buf, s)
2979
2980		buf = buf[reclen:]
2981		n += reclen
2982		cnt++
2983	}
2984	// Set the seek offset of the input fd to record
2985	// how many files we've already returned.
2986	_, err = Seek(fd, cnt, 0 /* SEEK_SET */)
2987	if err != nil {
2988		return n, err
2989	}
2990
2991	return n, nil
2992}
2993
2994func Err2ad() (eadd *int) {
2995	r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS___ERR2AD<<4)
2996	eadd = (*int)(unsafe.Pointer(r0))
2997	return
2998}
2999
3000func ZosConsolePrintf(format string, v ...interface{}) (int, error) {
3001	type __cmsg struct {
3002		_            uint16
3003		_            [2]uint8
3004		__msg_length uint32
3005		__msg        uintptr
3006		_            [4]uint8
3007	}
3008	msg := fmt.Sprintf(format, v...)
3009	strptr := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&msg)).Data)
3010	len := (*reflect.StringHeader)(unsafe.Pointer(&msg)).Len
3011	cmsg := __cmsg{__msg_length: uint32(len), __msg: uintptr(strptr)}
3012	cmd := uint32(0)
3013	runtime.EnterSyscall()
3014	rc, err2, err1 := CallLeFuncWithErr(GetZosLibVec()+SYS_____CONSOLE_A<<4, uintptr(unsafe.Pointer(&cmsg)), 0, uintptr(unsafe.Pointer(&cmd)))
3015	runtime.ExitSyscall()
3016	if rc != 0 {
3017		return 0, fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2)
3018	}
3019	return 0, nil
3020}
3021func ZosStringToEbcdicBytes(str string, nullterm bool) (ebcdicBytes []byte) {
3022	if nullterm {
3023		ebcdicBytes = []byte(str + "\x00")
3024	} else {
3025		ebcdicBytes = []byte(str)
3026	}
3027	A2e(ebcdicBytes)
3028	return
3029}
3030func ZosEbcdicBytesToString(b []byte, trimRight bool) (str string) {
3031	res := make([]byte, len(b))
3032	copy(res, b)
3033	E2a(res)
3034	if trimRight {
3035		str = string(bytes.TrimRight(res, " \x00"))
3036	} else {
3037		str = string(res)
3038	}
3039	return
3040}
3041
3042func fdToPath(dirfd int) (path string, err error) {
3043	var buffer [1024]byte
3044	// w_ctrl()
3045	ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4,
3046		[]uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))})
3047	if ret == 0 {
3048		zb := bytes.IndexByte(buffer[:], 0)
3049		if zb == -1 {
3050			zb = len(buffer)
3051		}
3052		// __e2a_l()
3053		runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4,
3054			[]uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)})
3055		return string(buffer[:zb]), nil
3056	}
3057	// __errno()
3058	errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4,
3059		[]uintptr{}))))
3060	// __errno2()
3061	errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4,
3062		[]uintptr{}))
3063	// strerror_r()
3064	ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4,
3065		[]uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024})
3066	if ret == 0 {
3067		zb := bytes.IndexByte(buffer[:], 0)
3068		if zb == -1 {
3069			zb = len(buffer)
3070		}
3071		return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2)
3072	} else {
3073		return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2)
3074	}
3075}
3076
3077func impl_Mkfifoat(dirfd int, path string, mode uint32) (err error) {
3078	var _p0 *byte
3079	_p0, err = BytePtrFromString(path)
3080	if err != nil {
3081		return
3082	}
3083	runtime.EnterSyscall()
3084	r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKFIFOAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
3085	runtime.ExitSyscall()
3086	if int64(r0) == -1 {
3087		err = errnoErr2(e1, e2)
3088	}
3089	return
3090}
3091
3092//go:nosplit
3093func get_MkfifoatAddr() *(func(dirfd int, path string, mode uint32) (err error))
3094
3095var Mkfifoat = enter_Mkfifoat
3096
3097func enter_Mkfifoat(dirfd int, path string, mode uint32) (err error) {
3098	funcref := get_MkfifoatAddr()
3099	if funcptrtest(GetZosLibVec()+SYS___MKFIFOAT_A<<4, "") == 0 {
3100		*funcref = impl_Mkfifoat
3101	} else {
3102		*funcref = legacy_Mkfifoat
3103	}
3104	return (*funcref)(dirfd, path, mode)
3105}
3106
3107func legacy_Mkfifoat(dirfd int, path string, mode uint32) (err error) {
3108	dirname, err := ZosFdToPath(dirfd)
3109	if err != nil {
3110		return err
3111	}
3112	return Mkfifo(dirname+"/"+path, mode)
3113}
3114
3115//sys	Posix_openpt(oflag int) (fd int, err error) = SYS_POSIX_OPENPT
3116//sys	Grantpt(fildes int) (rc int, err error) = SYS_GRANTPT
3117//sys	Unlockpt(fildes int) (rc int, err error) = SYS_UNLOCKPT
3118