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