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