golang.org/x/sys@v0.9.0/unix/syscall_zos_s390x.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build zos && s390x 6 // +build zos,s390x 7 8 package unix 9 10 import ( 11 "bytes" 12 "fmt" 13 "runtime" 14 "sort" 15 "strings" 16 "sync" 17 "syscall" 18 "unsafe" 19 ) 20 21 const ( 22 O_CLOEXEC = 0 // Dummy value (not supported). 23 AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX 24 ) 25 26 func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 27 func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 28 func syscall_syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 29 func syscall_rawsyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 30 func syscall_syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) 31 func syscall_rawsyscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) 32 33 func copyStat(stat *Stat_t, statLE *Stat_LE_t) { 34 stat.Dev = uint64(statLE.Dev) 35 stat.Ino = uint64(statLE.Ino) 36 stat.Nlink = uint64(statLE.Nlink) 37 stat.Mode = uint32(statLE.Mode) 38 stat.Uid = uint32(statLE.Uid) 39 stat.Gid = uint32(statLE.Gid) 40 stat.Rdev = uint64(statLE.Rdev) 41 stat.Size = statLE.Size 42 stat.Atim.Sec = int64(statLE.Atim) 43 stat.Atim.Nsec = 0 //zos doesn't return nanoseconds 44 stat.Mtim.Sec = int64(statLE.Mtim) 45 stat.Mtim.Nsec = 0 //zos doesn't return nanoseconds 46 stat.Ctim.Sec = int64(statLE.Ctim) 47 stat.Ctim.Nsec = 0 //zos doesn't return nanoseconds 48 stat.Blksize = int64(statLE.Blksize) 49 stat.Blocks = statLE.Blocks 50 } 51 52 func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64) 53 func svcLoad(name *byte) unsafe.Pointer 54 func svcUnload(name *byte, fnptr unsafe.Pointer) int64 55 56 func (d *Dirent) NameString() string { 57 if d == nil { 58 return "" 59 } 60 s := string(d.Name[:]) 61 idx := strings.IndexByte(s, 0) 62 if idx == -1 { 63 return s 64 } else { 65 return s[:idx] 66 } 67 } 68 69 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { 70 if sa.Port < 0 || sa.Port > 0xFFFF { 71 return nil, 0, EINVAL 72 } 73 sa.raw.Len = SizeofSockaddrInet4 74 sa.raw.Family = AF_INET 75 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 76 p[0] = byte(sa.Port >> 8) 77 p[1] = byte(sa.Port) 78 sa.raw.Addr = sa.Addr 79 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil 80 } 81 82 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { 83 if sa.Port < 0 || sa.Port > 0xFFFF { 84 return nil, 0, EINVAL 85 } 86 sa.raw.Len = SizeofSockaddrInet6 87 sa.raw.Family = AF_INET6 88 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 89 p[0] = byte(sa.Port >> 8) 90 p[1] = byte(sa.Port) 91 sa.raw.Scope_id = sa.ZoneId 92 sa.raw.Addr = sa.Addr 93 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil 94 } 95 96 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { 97 name := sa.Name 98 n := len(name) 99 if n >= len(sa.raw.Path) || n == 0 { 100 return nil, 0, EINVAL 101 } 102 sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL 103 sa.raw.Family = AF_UNIX 104 for i := 0; i < n; i++ { 105 sa.raw.Path[i] = int8(name[i]) 106 } 107 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil 108 } 109 110 func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) { 111 // TODO(neeilan): Implement use of first param (fd) 112 switch rsa.Addr.Family { 113 case AF_UNIX: 114 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 115 sa := new(SockaddrUnix) 116 // For z/OS, only replace NUL with @ when the 117 // length is not zero. 118 if pp.Len != 0 && pp.Path[0] == 0 { 119 // "Abstract" Unix domain socket. 120 // Rewrite leading NUL as @ for textual display. 121 // (This is the standard convention.) 122 // Not friendly to overwrite in place, 123 // but the callers below don't care. 124 pp.Path[0] = '@' 125 } 126 127 // Assume path ends at NUL. 128 // 129 // For z/OS, the length of the name is a field 130 // in the structure. To be on the safe side, we 131 // will still scan the name for a NUL but only 132 // to the length provided in the structure. 133 // 134 // This is not technically the Linux semantics for 135 // abstract Unix domain sockets--they are supposed 136 // to be uninterpreted fixed-size binary blobs--but 137 // everyone uses this convention. 138 n := 0 139 for n < int(pp.Len) && pp.Path[n] != 0 { 140 n++ 141 } 142 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) 143 return sa, nil 144 145 case AF_INET: 146 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 147 sa := new(SockaddrInet4) 148 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 149 sa.Port = int(p[0])<<8 + int(p[1]) 150 sa.Addr = pp.Addr 151 return sa, nil 152 153 case AF_INET6: 154 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 155 sa := new(SockaddrInet6) 156 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 157 sa.Port = int(p[0])<<8 + int(p[1]) 158 sa.ZoneId = pp.Scope_id 159 sa.Addr = pp.Addr 160 return sa, nil 161 } 162 return nil, EAFNOSUPPORT 163 } 164 165 func Accept(fd int) (nfd int, sa Sockaddr, err error) { 166 var rsa RawSockaddrAny 167 var len _Socklen = SizeofSockaddrAny 168 nfd, err = accept(fd, &rsa, &len) 169 if err != nil { 170 return 171 } 172 // TODO(neeilan): Remove 0 in call 173 sa, err = anyToSockaddr(0, &rsa) 174 if err != nil { 175 Close(nfd) 176 nfd = 0 177 } 178 return 179 } 180 181 func (iov *Iovec) SetLen(length int) { 182 iov.Len = uint64(length) 183 } 184 185 func (msghdr *Msghdr) SetControllen(length int) { 186 msghdr.Controllen = int32(length) 187 } 188 189 func (cmsg *Cmsghdr) SetLen(length int) { 190 cmsg.Len = int32(length) 191 } 192 193 //sys fcntl(fd int, cmd int, arg int) (val int, err error) 194 //sys read(fd int, p []byte) (n int, err error) 195 //sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ 196 //sys write(fd int, p []byte) (n int, err error) 197 198 //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = SYS___ACCEPT_A 199 //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___BIND_A 200 //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___CONNECT_A 201 //sysnb getgroups(n int, list *_Gid_t) (nn int, err error) 202 //sysnb setgroups(n int, list *_Gid_t) (err error) 203 //sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) 204 //sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) 205 //sysnb socket(domain int, typ int, proto int) (fd int, err error) 206 //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) 207 //sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETPEERNAME_A 208 //sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETSOCKNAME_A 209 //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = SYS___RECVFROM_A 210 //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = SYS___SENDTO_A 211 //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___RECVMSG_A 212 //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___SENDMSG_A 213 //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) = SYS_MMAP 214 //sys munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP 215 //sys ioctl(fd int, req int, arg uintptr) (err error) = SYS_IOCTL 216 //sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = SYS_IOCTL 217 218 //sys Access(path string, mode uint32) (err error) = SYS___ACCESS_A 219 //sys Chdir(path string) (err error) = SYS___CHDIR_A 220 //sys Chown(path string, uid int, gid int) (err error) = SYS___CHOWN_A 221 //sys Chmod(path string, mode uint32) (err error) = SYS___CHMOD_A 222 //sys Creat(path string, mode uint32) (fd int, err error) = SYS___CREAT_A 223 //sys Dup(oldfd int) (fd int, err error) 224 //sys Dup2(oldfd int, newfd int) (err error) 225 //sys Errno2() (er2 int) = SYS___ERRNO2 226 //sys Err2ad() (eadd *int) = SYS___ERR2AD 227 //sys Exit(code int) 228 //sys Fchdir(fd int) (err error) 229 //sys Fchmod(fd int, mode uint32) (err error) 230 //sys Fchown(fd int, uid int, gid int) (err error) 231 //sys FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) = SYS_FCNTL 232 //sys fstat(fd int, stat *Stat_LE_t) (err error) 233 234 func Fstat(fd int, stat *Stat_t) (err error) { 235 var statLE Stat_LE_t 236 err = fstat(fd, &statLE) 237 copyStat(stat, &statLE) 238 return 239 } 240 241 //sys Fstatvfs(fd int, stat *Statvfs_t) (err error) = SYS_FSTATVFS 242 //sys Fsync(fd int) (err error) 243 //sys Ftruncate(fd int, length int64) (err error) 244 //sys Getpagesize() (pgsize int) = SYS_GETPAGESIZE 245 //sys Mprotect(b []byte, prot int) (err error) = SYS_MPROTECT 246 //sys Msync(b []byte, flags int) (err error) = SYS_MSYNC 247 //sys Poll(fds []PollFd, timeout int) (n int, err error) = SYS_POLL 248 //sys Times(tms *Tms) (ticks uintptr, err error) = SYS_TIMES 249 //sys W_Getmntent(buff *byte, size int) (lastsys int, err error) = SYS_W_GETMNTENT 250 //sys W_Getmntent_A(buff *byte, size int) (lastsys int, err error) = SYS___W_GETMNTENT_A 251 252 //sys mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) = SYS___MOUNT_A 253 //sys unmount(filesystem string, mtm int) (err error) = SYS___UMOUNT_A 254 //sys Chroot(path string) (err error) = SYS___CHROOT_A 255 //sys Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) = SYS_SELECT 256 //sysnb Uname(buf *Utsname) (err error) = SYS___UNAME_A 257 258 func Ptsname(fd int) (name string, err error) { 259 r0, _, e1 := syscall_syscall(SYS___PTSNAME_A, uintptr(fd), 0, 0) 260 name = u2s(unsafe.Pointer(r0)) 261 if e1 != 0 { 262 err = errnoErr(e1) 263 } 264 return 265 } 266 267 func u2s(cstr unsafe.Pointer) string { 268 str := (*[1024]uint8)(cstr) 269 i := 0 270 for str[i] != 0 { 271 i++ 272 } 273 return string(str[:i]) 274 } 275 276 func Close(fd int) (err error) { 277 _, _, e1 := syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0) 278 for i := 0; e1 == EAGAIN && i < 10; i++ { 279 _, _, _ = syscall_syscall(SYS_USLEEP, uintptr(10), 0, 0) 280 _, _, e1 = syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0) 281 } 282 if e1 != 0 { 283 err = errnoErr(e1) 284 } 285 return 286 } 287 288 var mapper = &mmapper{ 289 active: make(map[*byte][]byte), 290 mmap: mmap, 291 munmap: munmap, 292 } 293 294 // Dummy function: there are no semantics for Madvise on z/OS 295 func Madvise(b []byte, advice int) (err error) { 296 return 297 } 298 299 func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 300 return mapper.Mmap(fd, offset, length, prot, flags) 301 } 302 303 func Munmap(b []byte) (err error) { 304 return mapper.Munmap(b) 305 } 306 307 //sys Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A 308 //sysnb Getegid() (egid int) 309 //sysnb Geteuid() (uid int) 310 //sysnb Getgid() (gid int) 311 //sysnb Getpid() (pid int) 312 //sysnb Getpgid(pid int) (pgid int, err error) = SYS_GETPGID 313 314 func Getpgrp() (pid int) { 315 pid, _ = Getpgid(0) 316 return 317 } 318 319 //sysnb Getppid() (pid int) 320 //sys Getpriority(which int, who int) (prio int, err error) 321 //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_GETRLIMIT 322 323 //sysnb getrusage(who int, rusage *rusage_zos) (err error) = SYS_GETRUSAGE 324 325 func Getrusage(who int, rusage *Rusage) (err error) { 326 var ruz rusage_zos 327 err = getrusage(who, &ruz) 328 //Only the first two fields of Rusage are set 329 rusage.Utime.Sec = ruz.Utime.Sec 330 rusage.Utime.Usec = int64(ruz.Utime.Usec) 331 rusage.Stime.Sec = ruz.Stime.Sec 332 rusage.Stime.Usec = int64(ruz.Stime.Usec) 333 return 334 } 335 336 //sysnb Getsid(pid int) (sid int, err error) = SYS_GETSID 337 //sysnb Getuid() (uid int) 338 //sysnb Kill(pid int, sig Signal) (err error) 339 //sys Lchown(path string, uid int, gid int) (err error) = SYS___LCHOWN_A 340 //sys Link(path string, link string) (err error) = SYS___LINK_A 341 //sys Listen(s int, n int) (err error) 342 //sys lstat(path string, stat *Stat_LE_t) (err error) = SYS___LSTAT_A 343 344 func Lstat(path string, stat *Stat_t) (err error) { 345 var statLE Stat_LE_t 346 err = lstat(path, &statLE) 347 copyStat(stat, &statLE) 348 return 349 } 350 351 //sys Mkdir(path string, mode uint32) (err error) = SYS___MKDIR_A 352 //sys Mkfifo(path string, mode uint32) (err error) = SYS___MKFIFO_A 353 //sys Mknod(path string, mode uint32, dev int) (err error) = SYS___MKNOD_A 354 //sys Pread(fd int, p []byte, offset int64) (n int, err error) 355 //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) 356 //sys Readlink(path string, buf []byte) (n int, err error) = SYS___READLINK_A 357 //sys Rename(from string, to string) (err error) = SYS___RENAME_A 358 //sys Rmdir(path string) (err error) = SYS___RMDIR_A 359 //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK 360 //sys Setpriority(which int, who int, prio int) (err error) 361 //sysnb Setpgid(pid int, pgid int) (err error) = SYS_SETPGID 362 //sysnb Setrlimit(resource int, lim *Rlimit) (err error) 363 //sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID 364 //sysnb Setreuid(ruid int, euid int) (err error) = SYS_SETREUID 365 //sysnb Setsid() (pid int, err error) = SYS_SETSID 366 //sys Setuid(uid int) (err error) = SYS_SETUID 367 //sys Setgid(uid int) (err error) = SYS_SETGID 368 //sys Shutdown(fd int, how int) (err error) 369 //sys stat(path string, statLE *Stat_LE_t) (err error) = SYS___STAT_A 370 371 func Stat(path string, sta *Stat_t) (err error) { 372 var statLE Stat_LE_t 373 err = stat(path, &statLE) 374 copyStat(sta, &statLE) 375 return 376 } 377 378 //sys Symlink(path string, link string) (err error) = SYS___SYMLINK_A 379 //sys Sync() = SYS_SYNC 380 //sys Truncate(path string, length int64) (err error) = SYS___TRUNCATE_A 381 //sys Tcgetattr(fildes int, termptr *Termios) (err error) = SYS_TCGETATTR 382 //sys Tcsetattr(fildes int, when int, termptr *Termios) (err error) = SYS_TCSETATTR 383 //sys Umask(mask int) (oldmask int) 384 //sys Unlink(path string) (err error) = SYS___UNLINK_A 385 //sys Utime(path string, utim *Utimbuf) (err error) = SYS___UTIME_A 386 387 //sys open(path string, mode int, perm uint32) (fd int, err error) = SYS___OPEN_A 388 389 func Open(path string, mode int, perm uint32) (fd int, err error) { 390 return open(path, mode, perm) 391 } 392 393 func Mkfifoat(dirfd int, path string, mode uint32) (err error) { 394 wd, err := Getwd() 395 if err != nil { 396 return err 397 } 398 399 if err := Fchdir(dirfd); err != nil { 400 return err 401 } 402 defer Chdir(wd) 403 404 return Mkfifo(path, mode) 405 } 406 407 //sys remove(path string) (err error) 408 409 func Remove(path string) error { 410 return remove(path) 411 } 412 413 const ImplementsGetwd = true 414 415 func Getcwd(buf []byte) (n int, err error) { 416 var p unsafe.Pointer 417 if len(buf) > 0 { 418 p = unsafe.Pointer(&buf[0]) 419 } else { 420 p = unsafe.Pointer(&_zero) 421 } 422 _, _, e := syscall_syscall(SYS___GETCWD_A, uintptr(p), uintptr(len(buf)), 0) 423 n = clen(buf) + 1 424 if e != 0 { 425 err = errnoErr(e) 426 } 427 return 428 } 429 430 func Getwd() (wd string, err error) { 431 var buf [PathMax]byte 432 n, err := Getcwd(buf[0:]) 433 if err != nil { 434 return "", err 435 } 436 // Getcwd returns the number of bytes written to buf, including the NUL. 437 if n < 1 || n > len(buf) || buf[n-1] != 0 { 438 return "", EINVAL 439 } 440 return string(buf[0 : n-1]), nil 441 } 442 443 func Getgroups() (gids []int, err error) { 444 n, err := getgroups(0, nil) 445 if err != nil { 446 return nil, err 447 } 448 if n == 0 { 449 return nil, nil 450 } 451 452 // Sanity check group count. Max is 1<<16 on Linux. 453 if n < 0 || n > 1<<20 { 454 return nil, EINVAL 455 } 456 457 a := make([]_Gid_t, n) 458 n, err = getgroups(n, &a[0]) 459 if err != nil { 460 return nil, err 461 } 462 gids = make([]int, n) 463 for i, v := range a[0:n] { 464 gids[i] = int(v) 465 } 466 return 467 } 468 469 func Setgroups(gids []int) (err error) { 470 if len(gids) == 0 { 471 return setgroups(0, nil) 472 } 473 474 a := make([]_Gid_t, len(gids)) 475 for i, v := range gids { 476 a[i] = _Gid_t(v) 477 } 478 return setgroups(len(a), &a[0]) 479 } 480 481 func gettid() uint64 482 483 func Gettid() (tid int) { 484 return int(gettid()) 485 } 486 487 type WaitStatus uint32 488 489 // Wait status is 7 bits at bottom, either 0 (exited), 490 // 0x7F (stopped), or a signal number that caused an exit. 491 // The 0x80 bit is whether there was a core dump. 492 // An extra number (exit code, signal causing a stop) 493 // is in the high bits. At least that's the idea. 494 // There are various irregularities. For example, the 495 // "continued" status is 0xFFFF, distinguishing itself 496 // from stopped via the core dump bit. 497 498 const ( 499 mask = 0x7F 500 core = 0x80 501 exited = 0x00 502 stopped = 0x7F 503 shift = 8 504 ) 505 506 func (w WaitStatus) Exited() bool { return w&mask == exited } 507 508 func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited } 509 510 func (w WaitStatus) Stopped() bool { return w&0xFF == stopped } 511 512 func (w WaitStatus) Continued() bool { return w == 0xFFFF } 513 514 func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } 515 516 func (w WaitStatus) ExitStatus() int { 517 if !w.Exited() { 518 return -1 519 } 520 return int(w>>shift) & 0xFF 521 } 522 523 func (w WaitStatus) Signal() Signal { 524 if !w.Signaled() { 525 return -1 526 } 527 return Signal(w & mask) 528 } 529 530 func (w WaitStatus) StopSignal() Signal { 531 if !w.Stopped() { 532 return -1 533 } 534 return Signal(w>>shift) & 0xFF 535 } 536 537 func (w WaitStatus) TrapCause() int { return -1 } 538 539 //sys waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) 540 541 func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { 542 // TODO(mundaym): z/OS doesn't have wait4. I don't think getrusage does what we want. 543 // At the moment rusage will not be touched. 544 var status _C_int 545 wpid, err = waitpid(pid, &status, options) 546 if wstatus != nil { 547 *wstatus = WaitStatus(status) 548 } 549 return 550 } 551 552 //sysnb gettimeofday(tv *timeval_zos) (err error) 553 554 func Gettimeofday(tv *Timeval) (err error) { 555 var tvz timeval_zos 556 err = gettimeofday(&tvz) 557 tv.Sec = tvz.Sec 558 tv.Usec = int64(tvz.Usec) 559 return 560 } 561 562 func Time(t *Time_t) (tt Time_t, err error) { 563 var tv Timeval 564 err = Gettimeofday(&tv) 565 if err != nil { 566 return 0, err 567 } 568 if t != nil { 569 *t = Time_t(tv.Sec) 570 } 571 return Time_t(tv.Sec), nil 572 } 573 574 func setTimespec(sec, nsec int64) Timespec { 575 return Timespec{Sec: sec, Nsec: nsec} 576 } 577 578 func setTimeval(sec, usec int64) Timeval { //fix 579 return Timeval{Sec: sec, Usec: usec} 580 } 581 582 //sysnb pipe(p *[2]_C_int) (err error) 583 584 func Pipe(p []int) (err error) { 585 if len(p) != 2 { 586 return EINVAL 587 } 588 var pp [2]_C_int 589 err = pipe(&pp) 590 if err == nil { 591 p[0] = int(pp[0]) 592 p[1] = int(pp[1]) 593 } 594 return 595 } 596 597 //sys utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A 598 599 func Utimes(path string, tv []Timeval) (err error) { 600 if len(tv) != 2 { 601 return EINVAL 602 } 603 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 604 } 605 606 func UtimesNano(path string, ts []Timespec) error { 607 if len(ts) != 2 { 608 return EINVAL 609 } 610 // Not as efficient as it could be because Timespec and 611 // Timeval have different types in the different OSes 612 tv := [2]Timeval{ 613 NsecToTimeval(TimespecToNsec(ts[0])), 614 NsecToTimeval(TimespecToNsec(ts[1])), 615 } 616 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 617 } 618 619 func Getsockname(fd int) (sa Sockaddr, err error) { 620 var rsa RawSockaddrAny 621 var len _Socklen = SizeofSockaddrAny 622 if err = getsockname(fd, &rsa, &len); err != nil { 623 return 624 } 625 // TODO(neeilan) : Remove this 0 ( added to get sys/unix compiling on z/OS ) 626 return anyToSockaddr(0, &rsa) 627 } 628 629 const ( 630 // identifier constants 631 nwmHeaderIdentifier = 0xd5e6d4c8 632 nwmFilterIdentifier = 0xd5e6d4c6 633 nwmTCPConnIdentifier = 0xd5e6d4c3 634 nwmRecHeaderIdentifier = 0xd5e6d4d9 635 nwmIPStatsIdentifier = 0xd5e6d4c9d7e2e340 636 nwmIPGStatsIdentifier = 0xd5e6d4c9d7c7e2e3 637 nwmTCPStatsIdentifier = 0xd5e6d4e3c3d7e2e3 638 nwmUDPStatsIdentifier = 0xd5e6d4e4c4d7e2e3 639 nwmICMPGStatsEntry = 0xd5e6d4c9c3d4d7c7 640 nwmICMPTStatsEntry = 0xd5e6d4c9c3d4d7e3 641 642 // nwmHeader constants 643 nwmVersion1 = 1 644 nwmVersion2 = 2 645 nwmCurrentVer = 2 646 647 nwmTCPConnType = 1 648 nwmGlobalStatsType = 14 649 650 // nwmFilter constants 651 nwmFilterLclAddrMask = 0x20000000 // Local address 652 nwmFilterSrcAddrMask = 0x20000000 // Source address 653 nwmFilterLclPortMask = 0x10000000 // Local port 654 nwmFilterSrcPortMask = 0x10000000 // Source port 655 656 // nwmConnEntry constants 657 nwmTCPStateClosed = 1 658 nwmTCPStateListen = 2 659 nwmTCPStateSynSent = 3 660 nwmTCPStateSynRcvd = 4 661 nwmTCPStateEstab = 5 662 nwmTCPStateFinWait1 = 6 663 nwmTCPStateFinWait2 = 7 664 nwmTCPStateClosWait = 8 665 nwmTCPStateLastAck = 9 666 nwmTCPStateClosing = 10 667 nwmTCPStateTimeWait = 11 668 nwmTCPStateDeletTCB = 12 669 670 // Existing constants on linux 671 BPF_TCP_CLOSE = 1 672 BPF_TCP_LISTEN = 2 673 BPF_TCP_SYN_SENT = 3 674 BPF_TCP_SYN_RECV = 4 675 BPF_TCP_ESTABLISHED = 5 676 BPF_TCP_FIN_WAIT1 = 6 677 BPF_TCP_FIN_WAIT2 = 7 678 BPF_TCP_CLOSE_WAIT = 8 679 BPF_TCP_LAST_ACK = 9 680 BPF_TCP_CLOSING = 10 681 BPF_TCP_TIME_WAIT = 11 682 BPF_TCP_NEW_SYN_RECV = -1 683 BPF_TCP_MAX_STATES = -2 684 ) 685 686 type nwmTriplet struct { 687 offset uint32 688 length uint32 689 number uint32 690 } 691 692 type nwmQuadruplet struct { 693 offset uint32 694 length uint32 695 number uint32 696 match uint32 697 } 698 699 type nwmHeader struct { 700 ident uint32 701 length uint32 702 version uint16 703 nwmType uint16 704 bytesNeeded uint32 705 options uint32 706 _ [16]byte 707 inputDesc nwmTriplet 708 outputDesc nwmQuadruplet 709 } 710 711 type nwmFilter struct { 712 ident uint32 713 flags uint32 714 resourceName [8]byte 715 resourceId uint32 716 listenerId uint32 717 local [28]byte // union of sockaddr4 and sockaddr6 718 remote [28]byte // union of sockaddr4 and sockaddr6 719 _ uint16 720 _ uint16 721 asid uint16 722 _ [2]byte 723 tnLuName [8]byte 724 tnMonGrp uint32 725 tnAppl [8]byte 726 applData [40]byte 727 nInterface [16]byte 728 dVipa [16]byte 729 dVipaPfx uint16 730 dVipaPort uint16 731 dVipaFamily byte 732 _ [3]byte 733 destXCF [16]byte 734 destXCFPfx uint16 735 destXCFFamily byte 736 _ [1]byte 737 targIP [16]byte 738 targIPPfx uint16 739 targIPFamily byte 740 _ [1]byte 741 _ [20]byte 742 } 743 744 type nwmRecHeader struct { 745 ident uint32 746 length uint32 747 number byte 748 _ [3]byte 749 } 750 751 type nwmTCPStatsEntry struct { 752 ident uint64 753 currEstab uint32 754 activeOpened uint32 755 passiveOpened uint32 756 connClosed uint32 757 estabResets uint32 758 attemptFails uint32 759 passiveDrops uint32 760 timeWaitReused uint32 761 inSegs uint64 762 predictAck uint32 763 predictData uint32 764 inDupAck uint32 765 inBadSum uint32 766 inBadLen uint32 767 inShort uint32 768 inDiscOldTime uint32 769 inAllBeforeWin uint32 770 inSomeBeforeWin uint32 771 inAllAfterWin uint32 772 inSomeAfterWin uint32 773 inOutOfOrder uint32 774 inAfterClose uint32 775 inWinProbes uint32 776 inWinUpdates uint32 777 outWinUpdates uint32 778 outSegs uint64 779 outDelayAcks uint32 780 outRsts uint32 781 retransSegs uint32 782 retransTimeouts uint32 783 retransDrops uint32 784 pmtuRetrans uint32 785 pmtuErrors uint32 786 outWinProbes uint32 787 probeDrops uint32 788 keepAliveProbes uint32 789 keepAliveDrops uint32 790 finwait2Drops uint32 791 acceptCount uint64 792 inBulkQSegs uint64 793 inDiscards uint64 794 connFloods uint32 795 connStalls uint32 796 cfgEphemDef uint16 797 ephemInUse uint16 798 ephemHiWater uint16 799 flags byte 800 _ [1]byte 801 ephemExhaust uint32 802 smcRCurrEstabLnks uint32 803 smcRLnkActTimeOut uint32 804 smcRActLnkOpened uint32 805 smcRPasLnkOpened uint32 806 smcRLnksClosed uint32 807 smcRCurrEstab uint32 808 smcRActiveOpened uint32 809 smcRPassiveOpened uint32 810 smcRConnClosed uint32 811 smcRInSegs uint64 812 smcROutSegs uint64 813 smcRInRsts uint32 814 smcROutRsts uint32 815 smcDCurrEstabLnks uint32 816 smcDActLnkOpened uint32 817 smcDPasLnkOpened uint32 818 smcDLnksClosed uint32 819 smcDCurrEstab uint32 820 smcDActiveOpened uint32 821 smcDPassiveOpened uint32 822 smcDConnClosed uint32 823 smcDInSegs uint64 824 smcDOutSegs uint64 825 smcDInRsts uint32 826 smcDOutRsts uint32 827 } 828 829 type nwmConnEntry struct { 830 ident uint32 831 local [28]byte // union of sockaddr4 and sockaddr6 832 remote [28]byte // union of sockaddr4 and sockaddr6 833 startTime [8]byte // uint64, changed to prevent padding from being inserted 834 lastActivity [8]byte // uint64 835 bytesIn [8]byte // uint64 836 bytesOut [8]byte // uint64 837 inSegs [8]byte // uint64 838 outSegs [8]byte // uint64 839 state uint16 840 activeOpen byte 841 flag01 byte 842 outBuffered uint32 843 inBuffered uint32 844 maxSndWnd uint32 845 reXmtCount uint32 846 congestionWnd uint32 847 ssThresh uint32 848 roundTripTime uint32 849 roundTripVar uint32 850 sendMSS uint32 851 sndWnd uint32 852 rcvBufSize uint32 853 sndBufSize uint32 854 outOfOrderCount uint32 855 lcl0WindowCount uint32 856 rmt0WindowCount uint32 857 dupacks uint32 858 flag02 byte 859 sockOpt6Cont byte 860 asid uint16 861 resourceName [8]byte 862 resourceId uint32 863 subtask uint32 864 sockOpt byte 865 sockOpt6 byte 866 clusterConnFlag byte 867 proto byte 868 targetAppl [8]byte 869 luName [8]byte 870 clientUserId [8]byte 871 logMode [8]byte 872 timeStamp uint32 873 timeStampAge uint32 874 serverResourceId uint32 875 intfName [16]byte 876 ttlsStatPol byte 877 ttlsStatConn byte 878 ttlsSSLProt uint16 879 ttlsNegCiph [2]byte 880 ttlsSecType byte 881 ttlsFIPS140Mode byte 882 ttlsUserID [8]byte 883 applData [40]byte 884 inOldestTime [8]byte // uint64 885 outOldestTime [8]byte // uint64 886 tcpTrustedPartner byte 887 _ [3]byte 888 bulkDataIntfName [16]byte 889 ttlsNegCiph4 [4]byte 890 smcReason uint32 891 lclSMCLinkId uint32 892 rmtSMCLinkId uint32 893 smcStatus byte 894 smcFlags byte 895 _ [2]byte 896 rcvWnd uint32 897 lclSMCBufSz uint32 898 rmtSMCBufSz uint32 899 ttlsSessID [32]byte 900 ttlsSessIDLen int16 901 _ [1]byte 902 smcDStatus byte 903 smcDReason uint32 904 } 905 906 var svcNameTable [][]byte = [][]byte{ 907 []byte("\xc5\xe9\xc2\xd5\xd4\xc9\xc6\xf4"), // svc_EZBNMIF4 908 } 909 910 const ( 911 svc_EZBNMIF4 = 0 912 ) 913 914 func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) { 915 jobname := []byte("\x5c\x40\x40\x40\x40\x40\x40\x40") // "*" 916 responseBuffer := [4096]byte{0} 917 var bufferAlet, reasonCode uint32 = 0, 0 918 var bufferLen, returnValue, returnCode int32 = 4096, 0, 0 919 920 dsa := [18]uint64{0} 921 var argv [7]unsafe.Pointer 922 argv[0] = unsafe.Pointer(&jobname[0]) 923 argv[1] = unsafe.Pointer(&responseBuffer[0]) 924 argv[2] = unsafe.Pointer(&bufferAlet) 925 argv[3] = unsafe.Pointer(&bufferLen) 926 argv[4] = unsafe.Pointer(&returnValue) 927 argv[5] = unsafe.Pointer(&returnCode) 928 argv[6] = unsafe.Pointer(&reasonCode) 929 930 request := (*struct { 931 header nwmHeader 932 filter nwmFilter 933 })(unsafe.Pointer(&responseBuffer[0])) 934 935 EZBNMIF4 := svcLoad(&svcNameTable[svc_EZBNMIF4][0]) 936 if EZBNMIF4 == nil { 937 return nil, errnoErr(EINVAL) 938 } 939 940 // GetGlobalStats EZBNMIF4 call 941 request.header.ident = nwmHeaderIdentifier 942 request.header.length = uint32(unsafe.Sizeof(request.header)) 943 request.header.version = nwmCurrentVer 944 request.header.nwmType = nwmGlobalStatsType 945 request.header.options = 0x80000000 946 947 svcCall(EZBNMIF4, &argv[0], &dsa[0]) 948 949 // outputDesc field is filled by EZBNMIF4 on success 950 if returnCode != 0 || request.header.outputDesc.offset == 0 { 951 return nil, errnoErr(EINVAL) 952 } 953 954 // Check that EZBNMIF4 returned a nwmRecHeader 955 recHeader := (*nwmRecHeader)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset])) 956 if recHeader.ident != nwmRecHeaderIdentifier { 957 return nil, errnoErr(EINVAL) 958 } 959 960 // Parse nwmTriplets to get offsets of returned entries 961 var sections []*uint64 962 var sectionDesc *nwmTriplet = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[0])) 963 for i := uint32(0); i < uint32(recHeader.number); i++ { 964 offset := request.header.outputDesc.offset + uint32(unsafe.Sizeof(*recHeader)) + i*uint32(unsafe.Sizeof(*sectionDesc)) 965 sectionDesc = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[offset])) 966 for j := uint32(0); j < sectionDesc.number; j++ { 967 offset = request.header.outputDesc.offset + sectionDesc.offset + j*sectionDesc.length 968 sections = append(sections, (*uint64)(unsafe.Pointer(&responseBuffer[offset]))) 969 } 970 } 971 972 // Find nwmTCPStatsEntry in returned entries 973 var tcpStats *nwmTCPStatsEntry = nil 974 for _, ptr := range sections { 975 switch *ptr { 976 case nwmTCPStatsIdentifier: 977 if tcpStats != nil { 978 return nil, errnoErr(EINVAL) 979 } 980 tcpStats = (*nwmTCPStatsEntry)(unsafe.Pointer(ptr)) 981 case nwmIPStatsIdentifier: 982 case nwmIPGStatsIdentifier: 983 case nwmUDPStatsIdentifier: 984 case nwmICMPGStatsEntry: 985 case nwmICMPTStatsEntry: 986 default: 987 return nil, errnoErr(EINVAL) 988 } 989 } 990 if tcpStats == nil { 991 return nil, errnoErr(EINVAL) 992 } 993 994 // GetConnectionDetail EZBNMIF4 call 995 responseBuffer = [4096]byte{0} 996 dsa = [18]uint64{0} 997 bufferAlet, reasonCode = 0, 0 998 bufferLen, returnValue, returnCode = 4096, 0, 0 999 nameptr := (*uint32)(unsafe.Pointer(uintptr(0x21c))) // Get jobname of current process 1000 nameptr = (*uint32)(unsafe.Pointer(uintptr(*nameptr + 12))) 1001 argv[0] = unsafe.Pointer(uintptr(*nameptr)) 1002 1003 request.header.ident = nwmHeaderIdentifier 1004 request.header.length = uint32(unsafe.Sizeof(request.header)) 1005 request.header.version = nwmCurrentVer 1006 request.header.nwmType = nwmTCPConnType 1007 request.header.options = 0x80000000 1008 1009 request.filter.ident = nwmFilterIdentifier 1010 1011 var localSockaddr RawSockaddrAny 1012 socklen := _Socklen(SizeofSockaddrAny) 1013 err := getsockname(fd, &localSockaddr, &socklen) 1014 if err != nil { 1015 return nil, errnoErr(EINVAL) 1016 } 1017 if localSockaddr.Addr.Family == AF_INET { 1018 localSockaddr := (*RawSockaddrInet4)(unsafe.Pointer(&localSockaddr.Addr)) 1019 localSockFilter := (*RawSockaddrInet4)(unsafe.Pointer(&request.filter.local[0])) 1020 localSockFilter.Family = AF_INET 1021 var i int 1022 for i = 0; i < 4; i++ { 1023 if localSockaddr.Addr[i] != 0 { 1024 break 1025 } 1026 } 1027 if i != 4 { 1028 request.filter.flags |= nwmFilterLclAddrMask 1029 for i = 0; i < 4; i++ { 1030 localSockFilter.Addr[i] = localSockaddr.Addr[i] 1031 } 1032 } 1033 if localSockaddr.Port != 0 { 1034 request.filter.flags |= nwmFilterLclPortMask 1035 localSockFilter.Port = localSockaddr.Port 1036 } 1037 } else if localSockaddr.Addr.Family == AF_INET6 { 1038 localSockaddr := (*RawSockaddrInet6)(unsafe.Pointer(&localSockaddr.Addr)) 1039 localSockFilter := (*RawSockaddrInet6)(unsafe.Pointer(&request.filter.local[0])) 1040 localSockFilter.Family = AF_INET6 1041 var i int 1042 for i = 0; i < 16; i++ { 1043 if localSockaddr.Addr[i] != 0 { 1044 break 1045 } 1046 } 1047 if i != 16 { 1048 request.filter.flags |= nwmFilterLclAddrMask 1049 for i = 0; i < 16; i++ { 1050 localSockFilter.Addr[i] = localSockaddr.Addr[i] 1051 } 1052 } 1053 if localSockaddr.Port != 0 { 1054 request.filter.flags |= nwmFilterLclPortMask 1055 localSockFilter.Port = localSockaddr.Port 1056 } 1057 } 1058 1059 svcCall(EZBNMIF4, &argv[0], &dsa[0]) 1060 1061 // outputDesc field is filled by EZBNMIF4 on success 1062 if returnCode != 0 || request.header.outputDesc.offset == 0 { 1063 return nil, errnoErr(EINVAL) 1064 } 1065 1066 // Check that EZBNMIF4 returned a nwmConnEntry 1067 conn := (*nwmConnEntry)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset])) 1068 if conn.ident != nwmTCPConnIdentifier { 1069 return nil, errnoErr(EINVAL) 1070 } 1071 1072 // Copy data from the returned data structures into tcpInfo 1073 // Stats from nwmConnEntry are specific to that connection. 1074 // Stats from nwmTCPStatsEntry are global (to the interface?) 1075 // Fields may not be an exact match. Some fields have no equivalent. 1076 var tcpinfo TCPInfo 1077 tcpinfo.State = uint8(conn.state) 1078 tcpinfo.Ca_state = 0 // dummy 1079 tcpinfo.Retransmits = uint8(tcpStats.retransSegs) 1080 tcpinfo.Probes = uint8(tcpStats.outWinProbes) 1081 tcpinfo.Backoff = 0 // dummy 1082 tcpinfo.Options = 0 // dummy 1083 tcpinfo.Rto = tcpStats.retransTimeouts 1084 tcpinfo.Ato = tcpStats.outDelayAcks 1085 tcpinfo.Snd_mss = conn.sendMSS 1086 tcpinfo.Rcv_mss = conn.sendMSS // dummy 1087 tcpinfo.Unacked = 0 // dummy 1088 tcpinfo.Sacked = 0 // dummy 1089 tcpinfo.Lost = 0 // dummy 1090 tcpinfo.Retrans = conn.reXmtCount 1091 tcpinfo.Fackets = 0 // dummy 1092 tcpinfo.Last_data_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.lastActivity[0]))) 1093 tcpinfo.Last_ack_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.outOldestTime[0]))) 1094 tcpinfo.Last_data_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0]))) 1095 tcpinfo.Last_ack_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0]))) 1096 tcpinfo.Pmtu = conn.sendMSS // dummy, NWMIfRouteMtu is a candidate 1097 tcpinfo.Rcv_ssthresh = conn.ssThresh 1098 tcpinfo.Rtt = conn.roundTripTime 1099 tcpinfo.Rttvar = conn.roundTripVar 1100 tcpinfo.Snd_ssthresh = conn.ssThresh // dummy 1101 tcpinfo.Snd_cwnd = conn.congestionWnd 1102 tcpinfo.Advmss = conn.sendMSS // dummy 1103 tcpinfo.Reordering = 0 // dummy 1104 tcpinfo.Rcv_rtt = conn.roundTripTime // dummy 1105 tcpinfo.Rcv_space = conn.sendMSS // dummy 1106 tcpinfo.Total_retrans = conn.reXmtCount 1107 1108 svcUnload(&svcNameTable[svc_EZBNMIF4][0], EZBNMIF4) 1109 1110 return &tcpinfo, nil 1111 } 1112 1113 // GetsockoptString returns the string value of the socket option opt for the 1114 // socket associated with fd at the given socket level. 1115 func GetsockoptString(fd, level, opt int) (string, error) { 1116 buf := make([]byte, 256) 1117 vallen := _Socklen(len(buf)) 1118 err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen) 1119 if err != nil { 1120 return "", err 1121 } 1122 1123 return string(buf[:vallen-1]), nil 1124 } 1125 1126 func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { 1127 var msg Msghdr 1128 var rsa RawSockaddrAny 1129 msg.Name = (*byte)(unsafe.Pointer(&rsa)) 1130 msg.Namelen = SizeofSockaddrAny 1131 var iov Iovec 1132 if len(p) > 0 { 1133 iov.Base = (*byte)(unsafe.Pointer(&p[0])) 1134 iov.SetLen(len(p)) 1135 } 1136 var dummy byte 1137 if len(oob) > 0 { 1138 // receive at least one normal byte 1139 if len(p) == 0 { 1140 iov.Base = &dummy 1141 iov.SetLen(1) 1142 } 1143 msg.Control = (*byte)(unsafe.Pointer(&oob[0])) 1144 msg.SetControllen(len(oob)) 1145 } 1146 msg.Iov = &iov 1147 msg.Iovlen = 1 1148 if n, err = recvmsg(fd, &msg, flags); err != nil { 1149 return 1150 } 1151 oobn = int(msg.Controllen) 1152 recvflags = int(msg.Flags) 1153 // source address is only specified if the socket is unconnected 1154 if rsa.Addr.Family != AF_UNSPEC { 1155 // TODO(neeilan): Remove 0 arg added to get this compiling on z/OS 1156 from, err = anyToSockaddr(0, &rsa) 1157 } 1158 return 1159 } 1160 1161 func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { 1162 _, err = SendmsgN(fd, p, oob, to, flags) 1163 return 1164 } 1165 1166 func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { 1167 var ptr unsafe.Pointer 1168 var salen _Socklen 1169 if to != nil { 1170 var err error 1171 ptr, salen, err = to.sockaddr() 1172 if err != nil { 1173 return 0, err 1174 } 1175 } 1176 var msg Msghdr 1177 msg.Name = (*byte)(unsafe.Pointer(ptr)) 1178 msg.Namelen = int32(salen) 1179 var iov Iovec 1180 if len(p) > 0 { 1181 iov.Base = (*byte)(unsafe.Pointer(&p[0])) 1182 iov.SetLen(len(p)) 1183 } 1184 var dummy byte 1185 if len(oob) > 0 { 1186 // send at least one normal byte 1187 if len(p) == 0 { 1188 iov.Base = &dummy 1189 iov.SetLen(1) 1190 } 1191 msg.Control = (*byte)(unsafe.Pointer(&oob[0])) 1192 msg.SetControllen(len(oob)) 1193 } 1194 msg.Iov = &iov 1195 msg.Iovlen = 1 1196 if n, err = sendmsg(fd, &msg, flags); err != nil { 1197 return 0, err 1198 } 1199 if len(oob) > 0 && len(p) == 0 { 1200 n = 0 1201 } 1202 return n, nil 1203 } 1204 1205 func Opendir(name string) (uintptr, error) { 1206 p, err := BytePtrFromString(name) 1207 if err != nil { 1208 return 0, err 1209 } 1210 dir, _, e := syscall_syscall(SYS___OPENDIR_A, uintptr(unsafe.Pointer(p)), 0, 0) 1211 runtime.KeepAlive(unsafe.Pointer(p)) 1212 if e != 0 { 1213 err = errnoErr(e) 1214 } 1215 return dir, err 1216 } 1217 1218 // clearsyscall.Errno resets the errno value to 0. 1219 func clearErrno() 1220 1221 func Readdir(dir uintptr) (*Dirent, error) { 1222 var ent Dirent 1223 var res uintptr 1224 // __readdir_r_a returns errno at the end of the directory stream, rather than 0. 1225 // Therefore to avoid false positives we clear errno before calling it. 1226 1227 // TODO(neeilan): Commented this out to get sys/unix compiling on z/OS. Uncomment and fix. Error: "undefined: clearsyscall" 1228 //clearsyscall.Errno() // TODO(mundaym): check pre-emption rules. 1229 1230 e, _, _ := syscall_syscall(SYS___READDIR_R_A, dir, uintptr(unsafe.Pointer(&ent)), uintptr(unsafe.Pointer(&res))) 1231 var err error 1232 if e != 0 { 1233 err = errnoErr(Errno(e)) 1234 } 1235 if res == 0 { 1236 return nil, err 1237 } 1238 return &ent, err 1239 } 1240 1241 func readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) { 1242 r0, _, e1 := syscall_syscall(SYS___READDIR_R_A, dirp, uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) 1243 if int64(r0) == -1 { 1244 err = errnoErr(Errno(e1)) 1245 } 1246 return 1247 } 1248 1249 func Closedir(dir uintptr) error { 1250 _, _, e := syscall_syscall(SYS_CLOSEDIR, dir, 0, 0) 1251 if e != 0 { 1252 return errnoErr(e) 1253 } 1254 return nil 1255 } 1256 1257 func Seekdir(dir uintptr, pos int) { 1258 _, _, _ = syscall_syscall(SYS_SEEKDIR, dir, uintptr(pos), 0) 1259 } 1260 1261 func Telldir(dir uintptr) (int, error) { 1262 p, _, e := syscall_syscall(SYS_TELLDIR, dir, 0, 0) 1263 pos := int(p) 1264 if pos == -1 { 1265 return pos, errnoErr(e) 1266 } 1267 return pos, nil 1268 } 1269 1270 // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. 1271 func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { 1272 // struct flock is packed on z/OS. We can't emulate that in Go so 1273 // instead we pack it here. 1274 var flock [24]byte 1275 *(*int16)(unsafe.Pointer(&flock[0])) = lk.Type 1276 *(*int16)(unsafe.Pointer(&flock[2])) = lk.Whence 1277 *(*int64)(unsafe.Pointer(&flock[4])) = lk.Start 1278 *(*int64)(unsafe.Pointer(&flock[12])) = lk.Len 1279 *(*int32)(unsafe.Pointer(&flock[20])) = lk.Pid 1280 _, _, errno := syscall_syscall(SYS_FCNTL, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock))) 1281 lk.Type = *(*int16)(unsafe.Pointer(&flock[0])) 1282 lk.Whence = *(*int16)(unsafe.Pointer(&flock[2])) 1283 lk.Start = *(*int64)(unsafe.Pointer(&flock[4])) 1284 lk.Len = *(*int64)(unsafe.Pointer(&flock[12])) 1285 lk.Pid = *(*int32)(unsafe.Pointer(&flock[20])) 1286 if errno == 0 { 1287 return nil 1288 } 1289 return errno 1290 } 1291 1292 func Flock(fd int, how int) error { 1293 1294 var flock_type int16 1295 var fcntl_cmd int 1296 1297 switch how { 1298 case LOCK_SH | LOCK_NB: 1299 flock_type = F_RDLCK 1300 fcntl_cmd = F_SETLK 1301 case LOCK_EX | LOCK_NB: 1302 flock_type = F_WRLCK 1303 fcntl_cmd = F_SETLK 1304 case LOCK_EX: 1305 flock_type = F_WRLCK 1306 fcntl_cmd = F_SETLKW 1307 case LOCK_UN: 1308 flock_type = F_UNLCK 1309 fcntl_cmd = F_SETLKW 1310 default: 1311 } 1312 1313 flock := Flock_t{ 1314 Type: int16(flock_type), 1315 Whence: int16(0), 1316 Start: int64(0), 1317 Len: int64(0), 1318 Pid: int32(Getppid()), 1319 } 1320 1321 err := FcntlFlock(uintptr(fd), fcntl_cmd, &flock) 1322 return err 1323 } 1324 1325 func Mlock(b []byte) (err error) { 1326 _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0) 1327 if e1 != 0 { 1328 err = errnoErr(e1) 1329 } 1330 return 1331 } 1332 1333 func Mlock2(b []byte, flags int) (err error) { 1334 _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0) 1335 if e1 != 0 { 1336 err = errnoErr(e1) 1337 } 1338 return 1339 } 1340 1341 func Mlockall(flags int) (err error) { 1342 _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0) 1343 if e1 != 0 { 1344 err = errnoErr(e1) 1345 } 1346 return 1347 } 1348 1349 func Munlock(b []byte) (err error) { 1350 _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0) 1351 if e1 != 0 { 1352 err = errnoErr(e1) 1353 } 1354 return 1355 } 1356 1357 func Munlockall() (err error) { 1358 _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0) 1359 if e1 != 0 { 1360 err = errnoErr(e1) 1361 } 1362 return 1363 } 1364 1365 func ClockGettime(clockid int32, ts *Timespec) error { 1366 1367 var ticks_per_sec uint32 = 100 //TODO(kenan): value is currently hardcoded; need sysconf() call otherwise 1368 var nsec_per_sec int64 = 1000000000 1369 1370 if ts == nil { 1371 return EFAULT 1372 } 1373 if clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC { 1374 var nanotime int64 = runtime.Nanotime1() 1375 ts.Sec = nanotime / nsec_per_sec 1376 ts.Nsec = nanotime % nsec_per_sec 1377 } else if clockid == CLOCK_PROCESS_CPUTIME_ID || clockid == CLOCK_THREAD_CPUTIME_ID { 1378 var tm Tms 1379 _, err := Times(&tm) 1380 if err != nil { 1381 return EFAULT 1382 } 1383 ts.Sec = int64(tm.Utime / ticks_per_sec) 1384 ts.Nsec = int64(tm.Utime) * nsec_per_sec / int64(ticks_per_sec) 1385 } else { 1386 return EINVAL 1387 } 1388 return nil 1389 } 1390 1391 func Statfs(path string, stat *Statfs_t) (err error) { 1392 fd, err := open(path, O_RDONLY, 0) 1393 defer Close(fd) 1394 if err != nil { 1395 return err 1396 } 1397 return Fstatfs(fd, stat) 1398 } 1399 1400 var ( 1401 Stdin = 0 1402 Stdout = 1 1403 Stderr = 2 1404 ) 1405 1406 // Do the interface allocations only once for common 1407 // Errno values. 1408 var ( 1409 errEAGAIN error = syscall.EAGAIN 1410 errEINVAL error = syscall.EINVAL 1411 errENOENT error = syscall.ENOENT 1412 ) 1413 1414 var ( 1415 signalNameMapOnce sync.Once 1416 signalNameMap map[string]syscall.Signal 1417 ) 1418 1419 // errnoErr returns common boxed Errno values, to prevent 1420 // allocations at runtime. 1421 func errnoErr(e Errno) error { 1422 switch e { 1423 case 0: 1424 return nil 1425 case EAGAIN: 1426 return errEAGAIN 1427 case EINVAL: 1428 return errEINVAL 1429 case ENOENT: 1430 return errENOENT 1431 } 1432 return e 1433 } 1434 1435 // ErrnoName returns the error name for error number e. 1436 func ErrnoName(e Errno) string { 1437 i := sort.Search(len(errorList), func(i int) bool { 1438 return errorList[i].num >= e 1439 }) 1440 if i < len(errorList) && errorList[i].num == e { 1441 return errorList[i].name 1442 } 1443 return "" 1444 } 1445 1446 // SignalName returns the signal name for signal number s. 1447 func SignalName(s syscall.Signal) string { 1448 i := sort.Search(len(signalList), func(i int) bool { 1449 return signalList[i].num >= s 1450 }) 1451 if i < len(signalList) && signalList[i].num == s { 1452 return signalList[i].name 1453 } 1454 return "" 1455 } 1456 1457 // SignalNum returns the syscall.Signal for signal named s, 1458 // or 0 if a signal with such name is not found. 1459 // The signal name should start with "SIG". 1460 func SignalNum(s string) syscall.Signal { 1461 signalNameMapOnce.Do(func() { 1462 signalNameMap = make(map[string]syscall.Signal, len(signalList)) 1463 for _, signal := range signalList { 1464 signalNameMap[signal.name] = signal.num 1465 } 1466 }) 1467 return signalNameMap[s] 1468 } 1469 1470 // clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte. 1471 func clen(n []byte) int { 1472 i := bytes.IndexByte(n, 0) 1473 if i == -1 { 1474 i = len(n) 1475 } 1476 return i 1477 } 1478 1479 // Mmap manager, for use by operating system-specific implementations. 1480 1481 type mmapper struct { 1482 sync.Mutex 1483 active map[*byte][]byte // active mappings; key is last byte in mapping 1484 mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error) 1485 munmap func(addr uintptr, length uintptr) error 1486 } 1487 1488 func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 1489 if length <= 0 { 1490 return nil, EINVAL 1491 } 1492 1493 // Map the requested memory. 1494 addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset) 1495 if errno != nil { 1496 return nil, errno 1497 } 1498 1499 // Slice memory layout 1500 var sl = struct { 1501 addr uintptr 1502 len int 1503 cap int 1504 }{addr, length, length} 1505 1506 // Use unsafe to turn sl into a []byte. 1507 b := *(*[]byte)(unsafe.Pointer(&sl)) 1508 1509 // Register mapping in m and return it. 1510 p := &b[cap(b)-1] 1511 m.Lock() 1512 defer m.Unlock() 1513 m.active[p] = b 1514 return b, nil 1515 } 1516 1517 func (m *mmapper) Munmap(data []byte) (err error) { 1518 if len(data) == 0 || len(data) != cap(data) { 1519 return EINVAL 1520 } 1521 1522 // Find the base of the mapping. 1523 p := &data[cap(data)-1] 1524 m.Lock() 1525 defer m.Unlock() 1526 b := m.active[p] 1527 if b == nil || &b[0] != &data[0] { 1528 return EINVAL 1529 } 1530 1531 // Unmap the memory and update m. 1532 if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil { 1533 return errno 1534 } 1535 delete(m.active, p) 1536 return nil 1537 } 1538 1539 func Read(fd int, p []byte) (n int, err error) { 1540 n, err = read(fd, p) 1541 if raceenabled { 1542 if n > 0 { 1543 raceWriteRange(unsafe.Pointer(&p[0]), n) 1544 } 1545 if err == nil { 1546 raceAcquire(unsafe.Pointer(&ioSync)) 1547 } 1548 } 1549 return 1550 } 1551 1552 func Write(fd int, p []byte) (n int, err error) { 1553 if raceenabled { 1554 raceReleaseMerge(unsafe.Pointer(&ioSync)) 1555 } 1556 n, err = write(fd, p) 1557 if raceenabled && n > 0 { 1558 raceReadRange(unsafe.Pointer(&p[0]), n) 1559 } 1560 return 1561 } 1562 1563 // For testing: clients can set this flag to force 1564 // creation of IPv6 sockets to return EAFNOSUPPORT. 1565 var SocketDisableIPv6 bool 1566 1567 // Sockaddr represents a socket address. 1568 type Sockaddr interface { 1569 sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs 1570 } 1571 1572 // SockaddrInet4 implements the Sockaddr interface for AF_INET type sockets. 1573 type SockaddrInet4 struct { 1574 Port int 1575 Addr [4]byte 1576 raw RawSockaddrInet4 1577 } 1578 1579 // SockaddrInet6 implements the Sockaddr interface for AF_INET6 type sockets. 1580 type SockaddrInet6 struct { 1581 Port int 1582 ZoneId uint32 1583 Addr [16]byte 1584 raw RawSockaddrInet6 1585 } 1586 1587 // SockaddrUnix implements the Sockaddr interface for AF_UNIX type sockets. 1588 type SockaddrUnix struct { 1589 Name string 1590 raw RawSockaddrUnix 1591 } 1592 1593 func Bind(fd int, sa Sockaddr) (err error) { 1594 ptr, n, err := sa.sockaddr() 1595 if err != nil { 1596 return err 1597 } 1598 return bind(fd, ptr, n) 1599 } 1600 1601 func Connect(fd int, sa Sockaddr) (err error) { 1602 ptr, n, err := sa.sockaddr() 1603 if err != nil { 1604 return err 1605 } 1606 return connect(fd, ptr, n) 1607 } 1608 1609 func Getpeername(fd int) (sa Sockaddr, err error) { 1610 var rsa RawSockaddrAny 1611 var len _Socklen = SizeofSockaddrAny 1612 if err = getpeername(fd, &rsa, &len); err != nil { 1613 return 1614 } 1615 return anyToSockaddr(fd, &rsa) 1616 } 1617 1618 func GetsockoptByte(fd, level, opt int) (value byte, err error) { 1619 var n byte 1620 vallen := _Socklen(1) 1621 err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) 1622 return n, err 1623 } 1624 1625 func GetsockoptInt(fd, level, opt int) (value int, err error) { 1626 var n int32 1627 vallen := _Socklen(4) 1628 err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) 1629 return int(n), err 1630 } 1631 1632 func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) { 1633 vallen := _Socklen(4) 1634 err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) 1635 return value, err 1636 } 1637 1638 func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) { 1639 var value IPMreq 1640 vallen := _Socklen(SizeofIPMreq) 1641 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 1642 return &value, err 1643 } 1644 1645 func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) { 1646 var value IPv6Mreq 1647 vallen := _Socklen(SizeofIPv6Mreq) 1648 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 1649 return &value, err 1650 } 1651 1652 func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) { 1653 var value IPv6MTUInfo 1654 vallen := _Socklen(SizeofIPv6MTUInfo) 1655 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 1656 return &value, err 1657 } 1658 1659 func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) { 1660 var value ICMPv6Filter 1661 vallen := _Socklen(SizeofICMPv6Filter) 1662 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 1663 return &value, err 1664 } 1665 1666 func GetsockoptLinger(fd, level, opt int) (*Linger, error) { 1667 var linger Linger 1668 vallen := _Socklen(SizeofLinger) 1669 err := getsockopt(fd, level, opt, unsafe.Pointer(&linger), &vallen) 1670 return &linger, err 1671 } 1672 1673 func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) { 1674 var tv Timeval 1675 vallen := _Socklen(unsafe.Sizeof(tv)) 1676 err := getsockopt(fd, level, opt, unsafe.Pointer(&tv), &vallen) 1677 return &tv, err 1678 } 1679 1680 func GetsockoptUint64(fd, level, opt int) (value uint64, err error) { 1681 var n uint64 1682 vallen := _Socklen(8) 1683 err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) 1684 return n, err 1685 } 1686 1687 func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { 1688 var rsa RawSockaddrAny 1689 var len _Socklen = SizeofSockaddrAny 1690 if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil { 1691 return 1692 } 1693 if rsa.Addr.Family != AF_UNSPEC { 1694 from, err = anyToSockaddr(fd, &rsa) 1695 } 1696 return 1697 } 1698 1699 func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { 1700 ptr, n, err := to.sockaddr() 1701 if err != nil { 1702 return err 1703 } 1704 return sendto(fd, p, flags, ptr, n) 1705 } 1706 1707 func SetsockoptByte(fd, level, opt int, value byte) (err error) { 1708 return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1) 1709 } 1710 1711 func SetsockoptInt(fd, level, opt int, value int) (err error) { 1712 var n = int32(value) 1713 return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4) 1714 } 1715 1716 func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) { 1717 return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4) 1718 } 1719 1720 func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) { 1721 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq) 1722 } 1723 1724 func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) { 1725 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq) 1726 } 1727 1728 func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error { 1729 return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter) 1730 } 1731 1732 func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) { 1733 return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger) 1734 } 1735 1736 func SetsockoptString(fd, level, opt int, s string) (err error) { 1737 var p unsafe.Pointer 1738 if len(s) > 0 { 1739 p = unsafe.Pointer(&[]byte(s)[0]) 1740 } 1741 return setsockopt(fd, level, opt, p, uintptr(len(s))) 1742 } 1743 1744 func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) { 1745 return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv)) 1746 } 1747 1748 func SetsockoptUint64(fd, level, opt int, value uint64) (err error) { 1749 return setsockopt(fd, level, opt, unsafe.Pointer(&value), 8) 1750 } 1751 1752 func Socket(domain, typ, proto int) (fd int, err error) { 1753 if domain == AF_INET6 && SocketDisableIPv6 { 1754 return -1, EAFNOSUPPORT 1755 } 1756 fd, err = socket(domain, typ, proto) 1757 return 1758 } 1759 1760 func Socketpair(domain, typ, proto int) (fd [2]int, err error) { 1761 var fdx [2]int32 1762 err = socketpair(domain, typ, proto, &fdx) 1763 if err == nil { 1764 fd[0] = int(fdx[0]) 1765 fd[1] = int(fdx[1]) 1766 } 1767 return 1768 } 1769 1770 var ioSync int64 1771 1772 func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) } 1773 1774 func SetNonblock(fd int, nonblocking bool) (err error) { 1775 flag, err := fcntl(fd, F_GETFL, 0) 1776 if err != nil { 1777 return err 1778 } 1779 if nonblocking { 1780 flag |= O_NONBLOCK 1781 } else { 1782 flag &= ^O_NONBLOCK 1783 } 1784 _, err = fcntl(fd, F_SETFL, flag) 1785 return err 1786 } 1787 1788 // Exec calls execve(2), which replaces the calling executable in the process 1789 // tree. argv0 should be the full path to an executable ("/bin/ls") and the 1790 // executable name should also be the first argument in argv (["ls", "-l"]). 1791 // envv are the environment variables that should be passed to the new 1792 // process (["USER=go", "PWD=/tmp"]). 1793 func Exec(argv0 string, argv []string, envv []string) error { 1794 return syscall.Exec(argv0, argv, envv) 1795 } 1796 1797 func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { 1798 if needspace := 8 - len(fstype); needspace <= 0 { 1799 fstype = fstype[:8] 1800 } else { 1801 fstype += " "[:needspace] 1802 } 1803 return mount_LE(target, source, fstype, uint32(flags), int32(len(data)), data) 1804 } 1805 1806 func Unmount(name string, mtm int) (err error) { 1807 // mountpoint is always a full path and starts with a '/' 1808 // check if input string is not a mountpoint but a filesystem name 1809 if name[0] != '/' { 1810 return unmount(name, mtm) 1811 } 1812 // treat name as mountpoint 1813 b2s := func(arr []byte) string { 1814 nulli := bytes.IndexByte(arr, 0) 1815 if nulli == -1 { 1816 return string(arr) 1817 } else { 1818 return string(arr[:nulli]) 1819 } 1820 } 1821 var buffer struct { 1822 header W_Mnth 1823 fsinfo [64]W_Mntent 1824 } 1825 fsCount, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer))) 1826 if err != nil { 1827 return err 1828 } 1829 if fsCount == 0 { 1830 return EINVAL 1831 } 1832 for i := 0; i < fsCount; i++ { 1833 if b2s(buffer.fsinfo[i].Mountpoint[:]) == name { 1834 err = unmount(b2s(buffer.fsinfo[i].Fsname[:]), mtm) 1835 break 1836 } 1837 } 1838 return err 1839 } 1840 1841 func fdToPath(dirfd int) (path string, err error) { 1842 var buffer [1024]byte 1843 // w_ctrl() 1844 ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4, 1845 []uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))}) 1846 if ret == 0 { 1847 zb := bytes.IndexByte(buffer[:], 0) 1848 if zb == -1 { 1849 zb = len(buffer) 1850 } 1851 // __e2a_l() 1852 runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, 1853 []uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)}) 1854 return string(buffer[:zb]), nil 1855 } 1856 // __errno() 1857 errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, 1858 []uintptr{})))) 1859 // __errno2() 1860 errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4, 1861 []uintptr{})) 1862 // strerror_r() 1863 ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4, 1864 []uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024}) 1865 if ret == 0 { 1866 zb := bytes.IndexByte(buffer[:], 0) 1867 if zb == -1 { 1868 zb = len(buffer) 1869 } 1870 return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2) 1871 } else { 1872 return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2) 1873 } 1874 } 1875 1876 func direntLeToDirentUnix(dirent *direntLE, dir uintptr, path string) (Dirent, error) { 1877 var d Dirent 1878 1879 d.Ino = uint64(dirent.Ino) 1880 offset, err := Telldir(dir) 1881 if err != nil { 1882 return d, err 1883 } 1884 1885 d.Off = int64(offset) 1886 s := string(bytes.Split(dirent.Name[:], []byte{0})[0]) 1887 copy(d.Name[:], s) 1888 1889 d.Reclen = uint16(24 + len(d.NameString())) 1890 var st Stat_t 1891 path = path + "/" + s 1892 err = Lstat(path, &st) 1893 if err != nil { 1894 return d, err 1895 } 1896 1897 d.Type = uint8(st.Mode >> 24) 1898 return d, err 1899 } 1900 1901 func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { 1902 // Simulation of Getdirentries port from the Darwin implementation. 1903 // COMMENTS FROM DARWIN: 1904 // It's not the full required semantics, but should handle the case 1905 // of calling Getdirentries or ReadDirent repeatedly. 1906 // It won't handle assigning the results of lseek to *basep, or handle 1907 // the directory being edited underfoot. 1908 1909 skip, err := Seek(fd, 0, 1 /* SEEK_CUR */) 1910 if err != nil { 1911 return 0, err 1912 } 1913 1914 // Get path from fd to avoid unavailable call (fdopendir) 1915 path, err := fdToPath(fd) 1916 if err != nil { 1917 return 0, err 1918 } 1919 d, err := Opendir(path) 1920 if err != nil { 1921 return 0, err 1922 } 1923 defer Closedir(d) 1924 1925 var cnt int64 1926 for { 1927 var entryLE direntLE 1928 var entrypLE *direntLE 1929 e := readdir_r(d, &entryLE, &entrypLE) 1930 if e != nil { 1931 return n, e 1932 } 1933 if entrypLE == nil { 1934 break 1935 } 1936 if skip > 0 { 1937 skip-- 1938 cnt++ 1939 continue 1940 } 1941 1942 // Dirent on zos has a different structure 1943 entry, e := direntLeToDirentUnix(&entryLE, d, path) 1944 if e != nil { 1945 return n, e 1946 } 1947 1948 reclen := int(entry.Reclen) 1949 if reclen > len(buf) { 1950 // Not enough room. Return for now. 1951 // The counter will let us know where we should start up again. 1952 // Note: this strategy for suspending in the middle and 1953 // restarting is O(n^2) in the length of the directory. Oh well. 1954 break 1955 } 1956 1957 // Copy entry into return buffer. 1958 s := unsafe.Slice((*byte)(unsafe.Pointer(&entry)), reclen) 1959 copy(buf, s) 1960 1961 buf = buf[reclen:] 1962 n += reclen 1963 cnt++ 1964 } 1965 // Set the seek offset of the input fd to record 1966 // how many files we've already returned. 1967 _, err = Seek(fd, cnt, 0 /* SEEK_SET */) 1968 if err != nil { 1969 return n, err 1970 } 1971 1972 return n, nil 1973 } 1974 1975 func ReadDirent(fd int, buf []byte) (n int, err error) { 1976 var base = (*uintptr)(unsafe.Pointer(new(uint64))) 1977 return Getdirentries(fd, buf, base) 1978 } 1979 1980 func direntIno(buf []byte) (uint64, bool) { 1981 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) 1982 } 1983 1984 func direntReclen(buf []byte) (uint64, bool) { 1985 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) 1986 } 1987 1988 func direntNamlen(buf []byte) (uint64, bool) { 1989 reclen, ok := direntReclen(buf) 1990 if !ok { 1991 return 0, false 1992 } 1993 return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true 1994 }