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