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