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