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