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