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