blob: f8616f454ec69314df269833effb6e47128bebff [file] [log] [blame]
Andrea Campanella764f1ed2022-03-24 11:46:38 +01001// Copyright 2020 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build zos && s390x
6// +build zos,s390x
7
8package unix
9
10import (
11 "bytes"
12 "runtime"
13 "sort"
14 "sync"
15 "syscall"
16 "unsafe"
17)
18
19const (
20 O_CLOEXEC = 0 // Dummy value (not supported).
21 AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX
22)
23
24func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
25func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
26func syscall_syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
27func syscall_rawsyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
28func syscall_syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
29func syscall_rawsyscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
30
31func copyStat(stat *Stat_t, statLE *Stat_LE_t) {
32 stat.Dev = uint64(statLE.Dev)
33 stat.Ino = uint64(statLE.Ino)
34 stat.Nlink = uint64(statLE.Nlink)
35 stat.Mode = uint32(statLE.Mode)
36 stat.Uid = uint32(statLE.Uid)
37 stat.Gid = uint32(statLE.Gid)
38 stat.Rdev = uint64(statLE.Rdev)
39 stat.Size = statLE.Size
40 stat.Atim.Sec = int64(statLE.Atim)
41 stat.Atim.Nsec = 0 //zos doesn't return nanoseconds
42 stat.Mtim.Sec = int64(statLE.Mtim)
43 stat.Mtim.Nsec = 0 //zos doesn't return nanoseconds
44 stat.Ctim.Sec = int64(statLE.Ctim)
45 stat.Ctim.Nsec = 0 //zos doesn't return nanoseconds
46 stat.Blksize = int64(statLE.Blksize)
47 stat.Blocks = statLE.Blocks
48}
49
50func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
51func svcLoad(name *byte) unsafe.Pointer
52func svcUnload(name *byte, fnptr unsafe.Pointer) int64
53
54func (d *Dirent) NameString() string {
55 if d == nil {
56 return ""
57 }
58 return string(d.Name[:d.Namlen])
59}
60
61func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
62 if sa.Port < 0 || sa.Port > 0xFFFF {
63 return nil, 0, EINVAL
64 }
65 sa.raw.Len = SizeofSockaddrInet4
66 sa.raw.Family = AF_INET
67 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
68 p[0] = byte(sa.Port >> 8)
69 p[1] = byte(sa.Port)
kesavandc71914f2022-03-25 11:19:03 +053070 sa.raw.Addr = sa.Addr
Andrea Campanella764f1ed2022-03-24 11:46:38 +010071 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
72}
73
74func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
75 if sa.Port < 0 || sa.Port > 0xFFFF {
76 return nil, 0, EINVAL
77 }
78 sa.raw.Len = SizeofSockaddrInet6
79 sa.raw.Family = AF_INET6
80 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
81 p[0] = byte(sa.Port >> 8)
82 p[1] = byte(sa.Port)
83 sa.raw.Scope_id = sa.ZoneId
kesavandc71914f2022-03-25 11:19:03 +053084 sa.raw.Addr = sa.Addr
Andrea Campanella764f1ed2022-03-24 11:46:38 +010085 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
86}
87
88func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
89 name := sa.Name
90 n := len(name)
91 if n >= len(sa.raw.Path) || n == 0 {
92 return nil, 0, EINVAL
93 }
94 sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
95 sa.raw.Family = AF_UNIX
96 for i := 0; i < n; i++ {
97 sa.raw.Path[i] = int8(name[i])
98 }
99 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
100}
101
102func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) {
103 // TODO(neeilan): Implement use of first param (fd)
104 switch rsa.Addr.Family {
105 case AF_UNIX:
106 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
107 sa := new(SockaddrUnix)
108 // For z/OS, only replace NUL with @ when the
109 // length is not zero.
110 if pp.Len != 0 && pp.Path[0] == 0 {
111 // "Abstract" Unix domain socket.
112 // Rewrite leading NUL as @ for textual display.
113 // (This is the standard convention.)
114 // Not friendly to overwrite in place,
115 // but the callers below don't care.
116 pp.Path[0] = '@'
117 }
118
119 // Assume path ends at NUL.
120 //
121 // For z/OS, the length of the name is a field
122 // in the structure. To be on the safe side, we
123 // will still scan the name for a NUL but only
124 // to the length provided in the structure.
125 //
126 // This is not technically the Linux semantics for
127 // abstract Unix domain sockets--they are supposed
128 // to be uninterpreted fixed-size binary blobs--but
129 // everyone uses this convention.
130 n := 0
131 for n < int(pp.Len) && pp.Path[n] != 0 {
132 n++
133 }
134 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
135 sa.Name = string(bytes)
136 return sa, nil
137
138 case AF_INET:
139 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
140 sa := new(SockaddrInet4)
141 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
142 sa.Port = int(p[0])<<8 + int(p[1])
kesavandc71914f2022-03-25 11:19:03 +0530143 sa.Addr = pp.Addr
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100144 return sa, nil
145
146 case AF_INET6:
147 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
148 sa := new(SockaddrInet6)
149 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
150 sa.Port = int(p[0])<<8 + int(p[1])
151 sa.ZoneId = pp.Scope_id
kesavandc71914f2022-03-25 11:19:03 +0530152 sa.Addr = pp.Addr
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100153 return sa, nil
154 }
155 return nil, EAFNOSUPPORT
156}
157
158func Accept(fd int) (nfd int, sa Sockaddr, err error) {
159 var rsa RawSockaddrAny
160 var len _Socklen = SizeofSockaddrAny
161 nfd, err = accept(fd, &rsa, &len)
162 if err != nil {
163 return
164 }
165 // TODO(neeilan): Remove 0 in call
166 sa, err = anyToSockaddr(0, &rsa)
167 if err != nil {
168 Close(nfd)
169 nfd = 0
170 }
171 return
172}
173
174func (iov *Iovec) SetLen(length int) {
175 iov.Len = uint64(length)
176}
177
178func (msghdr *Msghdr) SetControllen(length int) {
179 msghdr.Controllen = int32(length)
180}
181
182func (cmsg *Cmsghdr) SetLen(length int) {
183 cmsg.Len = int32(length)
184}
185
186//sys fcntl(fd int, cmd int, arg int) (val int, err error)
187//sys read(fd int, p []byte) (n int, err error)
188//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
189//sys write(fd int, p []byte) (n int, err error)
190
191//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = SYS___ACCEPT_A
192//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___BIND_A
193//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___CONNECT_A
194//sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
195//sysnb setgroups(n int, list *_Gid_t) (err error)
196//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
197//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
198//sysnb socket(domain int, typ int, proto int) (fd int, err error)
199//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
200//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETPEERNAME_A
201//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETSOCKNAME_A
202//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = SYS___RECVFROM_A
203//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = SYS___SENDTO_A
204//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___RECVMSG_A
205//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___SENDMSG_A
206//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) = SYS_MMAP
207//sys munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP
208//sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL
209
210//sys Access(path string, mode uint32) (err error) = SYS___ACCESS_A
211//sys Chdir(path string) (err error) = SYS___CHDIR_A
212//sys Chown(path string, uid int, gid int) (err error) = SYS___CHOWN_A
213//sys Chmod(path string, mode uint32) (err error) = SYS___CHMOD_A
214//sys Creat(path string, mode uint32) (fd int, err error) = SYS___CREAT_A
215//sys Dup(oldfd int) (fd int, err error)
216//sys Dup2(oldfd int, newfd int) (err error)
217//sys Errno2() (er2 int) = SYS___ERRNO2
218//sys Err2ad() (eadd *int) = SYS___ERR2AD
219//sys Exit(code int)
220//sys Fchdir(fd int) (err error)
221//sys Fchmod(fd int, mode uint32) (err error)
222//sys Fchown(fd int, uid int, gid int) (err error)
223//sys FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) = SYS_FCNTL
224//sys fstat(fd int, stat *Stat_LE_t) (err error)
225
226func Fstat(fd int, stat *Stat_t) (err error) {
227 var statLE Stat_LE_t
228 err = fstat(fd, &statLE)
229 copyStat(stat, &statLE)
230 return
231}
232
233//sys Fstatvfs(fd int, stat *Statvfs_t) (err error) = SYS_FSTATVFS
234//sys Fsync(fd int) (err error)
235//sys Ftruncate(fd int, length int64) (err error)
236//sys Getpagesize() (pgsize int) = SYS_GETPAGESIZE
237//sys Mprotect(b []byte, prot int) (err error) = SYS_MPROTECT
238//sys Msync(b []byte, flags int) (err error) = SYS_MSYNC
239//sys Poll(fds []PollFd, timeout int) (n int, err error) = SYS_POLL
240//sys Times(tms *Tms) (ticks uintptr, err error) = SYS_TIMES
241//sys W_Getmntent(buff *byte, size int) (lastsys int, err error) = SYS_W_GETMNTENT
242//sys W_Getmntent_A(buff *byte, size int) (lastsys int, err error) = SYS___W_GETMNTENT_A
243
244//sys mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) = SYS___MOUNT_A
245//sys unmount(filesystem string, mtm int) (err error) = SYS___UMOUNT_A
246//sys Chroot(path string) (err error) = SYS___CHROOT_A
247//sys Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) = SYS_SELECT
248//sysnb Uname(buf *Utsname) (err error) = SYS___UNAME_A
249
250func Ptsname(fd int) (name string, err error) {
251 r0, _, e1 := syscall_syscall(SYS___PTSNAME_A, uintptr(fd), 0, 0)
252 name = u2s(unsafe.Pointer(r0))
253 if e1 != 0 {
254 err = errnoErr(e1)
255 }
256 return
257}
258
259func u2s(cstr unsafe.Pointer) string {
260 str := (*[1024]uint8)(cstr)
261 i := 0
262 for str[i] != 0 {
263 i++
264 }
265 return string(str[:i])
266}
267
268func Close(fd int) (err error) {
269 _, _, e1 := syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0)
270 for i := 0; e1 == EAGAIN && i < 10; i++ {
271 _, _, _ = syscall_syscall(SYS_USLEEP, uintptr(10), 0, 0)
272 _, _, e1 = syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0)
273 }
274 if e1 != 0 {
275 err = errnoErr(e1)
276 }
277 return
278}
279
280var mapper = &mmapper{
281 active: make(map[*byte][]byte),
282 mmap: mmap,
283 munmap: munmap,
284}
285
286// Dummy function: there are no semantics for Madvise on z/OS
287func Madvise(b []byte, advice int) (err error) {
288 return
289}
290
291func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
292 return mapper.Mmap(fd, offset, length, prot, flags)
293}
294
295func Munmap(b []byte) (err error) {
296 return mapper.Munmap(b)
297}
298
299//sys Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A
300//sysnb Getegid() (egid int)
301//sysnb Geteuid() (uid int)
302//sysnb Getgid() (gid int)
303//sysnb Getpid() (pid int)
304//sysnb Getpgid(pid int) (pgid int, err error) = SYS_GETPGID
305
306func Getpgrp() (pid int) {
307 pid, _ = Getpgid(0)
308 return
309}
310
311//sysnb Getppid() (pid int)
312//sys Getpriority(which int, who int) (prio int, err error)
313//sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_GETRLIMIT
314
315//sysnb getrusage(who int, rusage *rusage_zos) (err error) = SYS_GETRUSAGE
316
317func Getrusage(who int, rusage *Rusage) (err error) {
318 var ruz rusage_zos
319 err = getrusage(who, &ruz)
320 //Only the first two fields of Rusage are set
321 rusage.Utime.Sec = ruz.Utime.Sec
322 rusage.Utime.Usec = int64(ruz.Utime.Usec)
323 rusage.Stime.Sec = ruz.Stime.Sec
324 rusage.Stime.Usec = int64(ruz.Stime.Usec)
325 return
326}
327
328//sysnb Getsid(pid int) (sid int, err error) = SYS_GETSID
329//sysnb Getuid() (uid int)
330//sysnb Kill(pid int, sig Signal) (err error)
331//sys Lchown(path string, uid int, gid int) (err error) = SYS___LCHOWN_A
332//sys Link(path string, link string) (err error) = SYS___LINK_A
333//sys Listen(s int, n int) (err error)
334//sys lstat(path string, stat *Stat_LE_t) (err error) = SYS___LSTAT_A
335
336func Lstat(path string, stat *Stat_t) (err error) {
337 var statLE Stat_LE_t
338 err = lstat(path, &statLE)
339 copyStat(stat, &statLE)
340 return
341}
342
343//sys Mkdir(path string, mode uint32) (err error) = SYS___MKDIR_A
344//sys Mkfifo(path string, mode uint32) (err error) = SYS___MKFIFO_A
345//sys Mknod(path string, mode uint32, dev int) (err error) = SYS___MKNOD_A
346//sys Pread(fd int, p []byte, offset int64) (n int, err error)
347//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
348//sys Readlink(path string, buf []byte) (n int, err error) = SYS___READLINK_A
349//sys Rename(from string, to string) (err error) = SYS___RENAME_A
350//sys Rmdir(path string) (err error) = SYS___RMDIR_A
351//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
352//sys Setpriority(which int, who int, prio int) (err error)
353//sysnb Setpgid(pid int, pgid int) (err error) = SYS_SETPGID
354//sysnb Setrlimit(resource int, lim *Rlimit) (err error)
355//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID
356//sysnb Setreuid(ruid int, euid int) (err error) = SYS_SETREUID
357//sysnb Setsid() (pid int, err error) = SYS_SETSID
358//sys Setuid(uid int) (err error) = SYS_SETUID
359//sys Setgid(uid int) (err error) = SYS_SETGID
360//sys Shutdown(fd int, how int) (err error)
361//sys stat(path string, statLE *Stat_LE_t) (err error) = SYS___STAT_A
362
363func Stat(path string, sta *Stat_t) (err error) {
364 var statLE Stat_LE_t
365 err = stat(path, &statLE)
366 copyStat(sta, &statLE)
367 return
368}
369
370//sys Symlink(path string, link string) (err error) = SYS___SYMLINK_A
371//sys Sync() = SYS_SYNC
372//sys Truncate(path string, length int64) (err error) = SYS___TRUNCATE_A
373//sys Tcgetattr(fildes int, termptr *Termios) (err error) = SYS_TCGETATTR
374//sys Tcsetattr(fildes int, when int, termptr *Termios) (err error) = SYS_TCSETATTR
375//sys Umask(mask int) (oldmask int)
376//sys Unlink(path string) (err error) = SYS___UNLINK_A
377//sys Utime(path string, utim *Utimbuf) (err error) = SYS___UTIME_A
378
379//sys open(path string, mode int, perm uint32) (fd int, err error) = SYS___OPEN_A
380
381func Open(path string, mode int, perm uint32) (fd int, err error) {
382 return open(path, mode, perm)
383}
384
385func Mkfifoat(dirfd int, path string, mode uint32) (err error) {
386 wd, err := Getwd()
387 if err != nil {
388 return err
389 }
390
391 if err := Fchdir(dirfd); err != nil {
392 return err
393 }
394 defer Chdir(wd)
395
396 return Mkfifo(path, mode)
397}
398
399//sys remove(path string) (err error)
400
401func Remove(path string) error {
402 return remove(path)
403}
404
405const ImplementsGetwd = true
406
407func Getcwd(buf []byte) (n int, err error) {
408 var p unsafe.Pointer
409 if len(buf) > 0 {
410 p = unsafe.Pointer(&buf[0])
411 } else {
412 p = unsafe.Pointer(&_zero)
413 }
414 _, _, e := syscall_syscall(SYS___GETCWD_A, uintptr(p), uintptr(len(buf)), 0)
415 n = clen(buf) + 1
416 if e != 0 {
417 err = errnoErr(e)
418 }
419 return
420}
421
422func Getwd() (wd string, err error) {
423 var buf [PathMax]byte
424 n, err := Getcwd(buf[0:])
425 if err != nil {
426 return "", err
427 }
428 // Getcwd returns the number of bytes written to buf, including the NUL.
429 if n < 1 || n > len(buf) || buf[n-1] != 0 {
430 return "", EINVAL
431 }
432 return string(buf[0 : n-1]), nil
433}
434
435func Getgroups() (gids []int, err error) {
436 n, err := getgroups(0, nil)
437 if err != nil {
438 return nil, err
439 }
440 if n == 0 {
441 return nil, nil
442 }
443
444 // Sanity check group count. Max is 1<<16 on Linux.
445 if n < 0 || n > 1<<20 {
446 return nil, EINVAL
447 }
448
449 a := make([]_Gid_t, n)
450 n, err = getgroups(n, &a[0])
451 if err != nil {
452 return nil, err
453 }
454 gids = make([]int, n)
455 for i, v := range a[0:n] {
456 gids[i] = int(v)
457 }
458 return
459}
460
461func Setgroups(gids []int) (err error) {
462 if len(gids) == 0 {
463 return setgroups(0, nil)
464 }
465
466 a := make([]_Gid_t, len(gids))
467 for i, v := range gids {
468 a[i] = _Gid_t(v)
469 }
470 return setgroups(len(a), &a[0])
471}
472
473func gettid() uint64
474
475func Gettid() (tid int) {
476 return int(gettid())
477}
478
479type WaitStatus uint32
480
481// Wait status is 7 bits at bottom, either 0 (exited),
482// 0x7F (stopped), or a signal number that caused an exit.
483// The 0x80 bit is whether there was a core dump.
484// An extra number (exit code, signal causing a stop)
485// is in the high bits. At least that's the idea.
486// There are various irregularities. For example, the
487// "continued" status is 0xFFFF, distinguishing itself
488// from stopped via the core dump bit.
489
490const (
491 mask = 0x7F
492 core = 0x80
493 exited = 0x00
494 stopped = 0x7F
495 shift = 8
496)
497
498func (w WaitStatus) Exited() bool { return w&mask == exited }
499
500func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited }
501
502func (w WaitStatus) Stopped() bool { return w&0xFF == stopped }
503
504func (w WaitStatus) Continued() bool { return w == 0xFFFF }
505
506func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
507
508func (w WaitStatus) ExitStatus() int {
509 if !w.Exited() {
510 return -1
511 }
512 return int(w>>shift) & 0xFF
513}
514
515func (w WaitStatus) Signal() Signal {
516 if !w.Signaled() {
517 return -1
518 }
519 return Signal(w & mask)
520}
521
522func (w WaitStatus) StopSignal() Signal {
523 if !w.Stopped() {
524 return -1
525 }
526 return Signal(w>>shift) & 0xFF
527}
528
529func (w WaitStatus) TrapCause() int { return -1 }
530
531//sys waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error)
532
533func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
534 // TODO(mundaym): z/OS doesn't have wait4. I don't think getrusage does what we want.
535 // At the moment rusage will not be touched.
536 var status _C_int
537 wpid, err = waitpid(pid, &status, options)
538 if wstatus != nil {
539 *wstatus = WaitStatus(status)
540 }
541 return
542}
543
544//sysnb gettimeofday(tv *timeval_zos) (err error)
545
546func Gettimeofday(tv *Timeval) (err error) {
547 var tvz timeval_zos
548 err = gettimeofday(&tvz)
549 tv.Sec = tvz.Sec
550 tv.Usec = int64(tvz.Usec)
551 return
552}
553
554func Time(t *Time_t) (tt Time_t, err error) {
555 var tv Timeval
556 err = Gettimeofday(&tv)
557 if err != nil {
558 return 0, err
559 }
560 if t != nil {
561 *t = Time_t(tv.Sec)
562 }
563 return Time_t(tv.Sec), nil
564}
565
566func setTimespec(sec, nsec int64) Timespec {
567 return Timespec{Sec: sec, Nsec: nsec}
568}
569
570func setTimeval(sec, usec int64) Timeval { //fix
571 return Timeval{Sec: sec, Usec: usec}
572}
573
574//sysnb pipe(p *[2]_C_int) (err error)
575
576func Pipe(p []int) (err error) {
577 if len(p) != 2 {
578 return EINVAL
579 }
580 var pp [2]_C_int
581 err = pipe(&pp)
kesavandc71914f2022-03-25 11:19:03 +0530582 if err == nil {
583 p[0] = int(pp[0])
584 p[1] = int(pp[1])
585 }
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100586 return
587}
588
589//sys utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A
590
591func Utimes(path string, tv []Timeval) (err error) {
592 if len(tv) != 2 {
593 return EINVAL
594 }
595 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
596}
597
598func UtimesNano(path string, ts []Timespec) error {
599 if len(ts) != 2 {
600 return EINVAL
601 }
602 // Not as efficient as it could be because Timespec and
603 // Timeval have different types in the different OSes
604 tv := [2]Timeval{
605 NsecToTimeval(TimespecToNsec(ts[0])),
606 NsecToTimeval(TimespecToNsec(ts[1])),
607 }
608 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
609}
610
611func Getsockname(fd int) (sa Sockaddr, err error) {
612 var rsa RawSockaddrAny
613 var len _Socklen = SizeofSockaddrAny
614 if err = getsockname(fd, &rsa, &len); err != nil {
615 return
616 }
617 // TODO(neeilan) : Remove this 0 ( added to get sys/unix compiling on z/OS )
618 return anyToSockaddr(0, &rsa)
619}
620
621const (
622 // identifier constants
623 nwmHeaderIdentifier = 0xd5e6d4c8
624 nwmFilterIdentifier = 0xd5e6d4c6
625 nwmTCPConnIdentifier = 0xd5e6d4c3
626 nwmRecHeaderIdentifier = 0xd5e6d4d9
627 nwmIPStatsIdentifier = 0xd5e6d4c9d7e2e340
628 nwmIPGStatsIdentifier = 0xd5e6d4c9d7c7e2e3
629 nwmTCPStatsIdentifier = 0xd5e6d4e3c3d7e2e3
630 nwmUDPStatsIdentifier = 0xd5e6d4e4c4d7e2e3
631 nwmICMPGStatsEntry = 0xd5e6d4c9c3d4d7c7
632 nwmICMPTStatsEntry = 0xd5e6d4c9c3d4d7e3
633
634 // nwmHeader constants
635 nwmVersion1 = 1
636 nwmVersion2 = 2
637 nwmCurrentVer = 2
638
639 nwmTCPConnType = 1
640 nwmGlobalStatsType = 14
641
642 // nwmFilter constants
643 nwmFilterLclAddrMask = 0x20000000 // Local address
644 nwmFilterSrcAddrMask = 0x20000000 // Source address
645 nwmFilterLclPortMask = 0x10000000 // Local port
646 nwmFilterSrcPortMask = 0x10000000 // Source port
647
648 // nwmConnEntry constants
649 nwmTCPStateClosed = 1
650 nwmTCPStateListen = 2
651 nwmTCPStateSynSent = 3
652 nwmTCPStateSynRcvd = 4
653 nwmTCPStateEstab = 5
654 nwmTCPStateFinWait1 = 6
655 nwmTCPStateFinWait2 = 7
656 nwmTCPStateClosWait = 8
657 nwmTCPStateLastAck = 9
658 nwmTCPStateClosing = 10
659 nwmTCPStateTimeWait = 11
660 nwmTCPStateDeletTCB = 12
661
662 // Existing constants on linux
663 BPF_TCP_CLOSE = 1
664 BPF_TCP_LISTEN = 2
665 BPF_TCP_SYN_SENT = 3
666 BPF_TCP_SYN_RECV = 4
667 BPF_TCP_ESTABLISHED = 5
668 BPF_TCP_FIN_WAIT1 = 6
669 BPF_TCP_FIN_WAIT2 = 7
670 BPF_TCP_CLOSE_WAIT = 8
671 BPF_TCP_LAST_ACK = 9
672 BPF_TCP_CLOSING = 10
673 BPF_TCP_TIME_WAIT = 11
674 BPF_TCP_NEW_SYN_RECV = -1
675 BPF_TCP_MAX_STATES = -2
676)
677
678type nwmTriplet struct {
679 offset uint32
680 length uint32
681 number uint32
682}
683
684type nwmQuadruplet struct {
685 offset uint32
686 length uint32
687 number uint32
688 match uint32
689}
690
691type nwmHeader struct {
692 ident uint32
693 length uint32
694 version uint16
695 nwmType uint16
696 bytesNeeded uint32
697 options uint32
698 _ [16]byte
699 inputDesc nwmTriplet
700 outputDesc nwmQuadruplet
701}
702
703type nwmFilter struct {
704 ident uint32
705 flags uint32
706 resourceName [8]byte
707 resourceId uint32
708 listenerId uint32
709 local [28]byte // union of sockaddr4 and sockaddr6
710 remote [28]byte // union of sockaddr4 and sockaddr6
711 _ uint16
712 _ uint16
713 asid uint16
714 _ [2]byte
715 tnLuName [8]byte
716 tnMonGrp uint32
717 tnAppl [8]byte
718 applData [40]byte
719 nInterface [16]byte
720 dVipa [16]byte
721 dVipaPfx uint16
722 dVipaPort uint16
723 dVipaFamily byte
724 _ [3]byte
725 destXCF [16]byte
726 destXCFPfx uint16
727 destXCFFamily byte
728 _ [1]byte
729 targIP [16]byte
730 targIPPfx uint16
731 targIPFamily byte
732 _ [1]byte
733 _ [20]byte
734}
735
736type nwmRecHeader struct {
737 ident uint32
738 length uint32
739 number byte
740 _ [3]byte
741}
742
743type nwmTCPStatsEntry struct {
744 ident uint64
745 currEstab uint32
746 activeOpened uint32
747 passiveOpened uint32
748 connClosed uint32
749 estabResets uint32
750 attemptFails uint32
751 passiveDrops uint32
752 timeWaitReused uint32
753 inSegs uint64
754 predictAck uint32
755 predictData uint32
756 inDupAck uint32
757 inBadSum uint32
758 inBadLen uint32
759 inShort uint32
760 inDiscOldTime uint32
761 inAllBeforeWin uint32
762 inSomeBeforeWin uint32
763 inAllAfterWin uint32
764 inSomeAfterWin uint32
765 inOutOfOrder uint32
766 inAfterClose uint32
767 inWinProbes uint32
768 inWinUpdates uint32
769 outWinUpdates uint32
770 outSegs uint64
771 outDelayAcks uint32
772 outRsts uint32
773 retransSegs uint32
774 retransTimeouts uint32
775 retransDrops uint32
776 pmtuRetrans uint32
777 pmtuErrors uint32
778 outWinProbes uint32
779 probeDrops uint32
780 keepAliveProbes uint32
781 keepAliveDrops uint32
782 finwait2Drops uint32
783 acceptCount uint64
784 inBulkQSegs uint64
785 inDiscards uint64
786 connFloods uint32
787 connStalls uint32
788 cfgEphemDef uint16
789 ephemInUse uint16
790 ephemHiWater uint16
791 flags byte
792 _ [1]byte
793 ephemExhaust uint32
794 smcRCurrEstabLnks uint32
795 smcRLnkActTimeOut uint32
796 smcRActLnkOpened uint32
797 smcRPasLnkOpened uint32
798 smcRLnksClosed uint32
799 smcRCurrEstab uint32
800 smcRActiveOpened uint32
801 smcRPassiveOpened uint32
802 smcRConnClosed uint32
803 smcRInSegs uint64
804 smcROutSegs uint64
805 smcRInRsts uint32
806 smcROutRsts uint32
807 smcDCurrEstabLnks uint32
808 smcDActLnkOpened uint32
809 smcDPasLnkOpened uint32
810 smcDLnksClosed uint32
811 smcDCurrEstab uint32
812 smcDActiveOpened uint32
813 smcDPassiveOpened uint32
814 smcDConnClosed uint32
815 smcDInSegs uint64
816 smcDOutSegs uint64
817 smcDInRsts uint32
818 smcDOutRsts uint32
819}
820
821type nwmConnEntry struct {
822 ident uint32
823 local [28]byte // union of sockaddr4 and sockaddr6
824 remote [28]byte // union of sockaddr4 and sockaddr6
825 startTime [8]byte // uint64, changed to prevent padding from being inserted
826 lastActivity [8]byte // uint64
827 bytesIn [8]byte // uint64
828 bytesOut [8]byte // uint64
829 inSegs [8]byte // uint64
830 outSegs [8]byte // uint64
831 state uint16
832 activeOpen byte
833 flag01 byte
834 outBuffered uint32
835 inBuffered uint32
836 maxSndWnd uint32
837 reXmtCount uint32
838 congestionWnd uint32
839 ssThresh uint32
840 roundTripTime uint32
841 roundTripVar uint32
842 sendMSS uint32
843 sndWnd uint32
844 rcvBufSize uint32
845 sndBufSize uint32
846 outOfOrderCount uint32
847 lcl0WindowCount uint32
848 rmt0WindowCount uint32
849 dupacks uint32
850 flag02 byte
851 sockOpt6Cont byte
852 asid uint16
853 resourceName [8]byte
854 resourceId uint32
855 subtask uint32
856 sockOpt byte
857 sockOpt6 byte
858 clusterConnFlag byte
859 proto byte
860 targetAppl [8]byte
861 luName [8]byte
862 clientUserId [8]byte
863 logMode [8]byte
864 timeStamp uint32
865 timeStampAge uint32
866 serverResourceId uint32
867 intfName [16]byte
868 ttlsStatPol byte
869 ttlsStatConn byte
870 ttlsSSLProt uint16
871 ttlsNegCiph [2]byte
872 ttlsSecType byte
873 ttlsFIPS140Mode byte
874 ttlsUserID [8]byte
875 applData [40]byte
876 inOldestTime [8]byte // uint64
877 outOldestTime [8]byte // uint64
878 tcpTrustedPartner byte
879 _ [3]byte
880 bulkDataIntfName [16]byte
881 ttlsNegCiph4 [4]byte
882 smcReason uint32
883 lclSMCLinkId uint32
884 rmtSMCLinkId uint32
885 smcStatus byte
886 smcFlags byte
887 _ [2]byte
888 rcvWnd uint32
889 lclSMCBufSz uint32
890 rmtSMCBufSz uint32
891 ttlsSessID [32]byte
892 ttlsSessIDLen int16
893 _ [1]byte
894 smcDStatus byte
895 smcDReason uint32
896}
897
898var svcNameTable [][]byte = [][]byte{
899 []byte("\xc5\xe9\xc2\xd5\xd4\xc9\xc6\xf4"), // svc_EZBNMIF4
900}
901
902const (
903 svc_EZBNMIF4 = 0
904)
905
906func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) {
907 jobname := []byte("\x5c\x40\x40\x40\x40\x40\x40\x40") // "*"
908 responseBuffer := [4096]byte{0}
909 var bufferAlet, reasonCode uint32 = 0, 0
910 var bufferLen, returnValue, returnCode int32 = 4096, 0, 0
911
912 dsa := [18]uint64{0}
913 var argv [7]unsafe.Pointer
914 argv[0] = unsafe.Pointer(&jobname[0])
915 argv[1] = unsafe.Pointer(&responseBuffer[0])
916 argv[2] = unsafe.Pointer(&bufferAlet)
917 argv[3] = unsafe.Pointer(&bufferLen)
918 argv[4] = unsafe.Pointer(&returnValue)
919 argv[5] = unsafe.Pointer(&returnCode)
920 argv[6] = unsafe.Pointer(&reasonCode)
921
922 request := (*struct {
923 header nwmHeader
924 filter nwmFilter
925 })(unsafe.Pointer(&responseBuffer[0]))
926
927 EZBNMIF4 := svcLoad(&svcNameTable[svc_EZBNMIF4][0])
928 if EZBNMIF4 == nil {
929 return nil, errnoErr(EINVAL)
930 }
931
932 // GetGlobalStats EZBNMIF4 call
933 request.header.ident = nwmHeaderIdentifier
934 request.header.length = uint32(unsafe.Sizeof(request.header))
935 request.header.version = nwmCurrentVer
936 request.header.nwmType = nwmGlobalStatsType
937 request.header.options = 0x80000000
938
939 svcCall(EZBNMIF4, &argv[0], &dsa[0])
940
941 // outputDesc field is filled by EZBNMIF4 on success
942 if returnCode != 0 || request.header.outputDesc.offset == 0 {
943 return nil, errnoErr(EINVAL)
944 }
945
946 // Check that EZBNMIF4 returned a nwmRecHeader
947 recHeader := (*nwmRecHeader)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
948 if recHeader.ident != nwmRecHeaderIdentifier {
949 return nil, errnoErr(EINVAL)
950 }
951
952 // Parse nwmTriplets to get offsets of returned entries
953 var sections []*uint64
954 var sectionDesc *nwmTriplet = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[0]))
955 for i := uint32(0); i < uint32(recHeader.number); i++ {
956 offset := request.header.outputDesc.offset + uint32(unsafe.Sizeof(*recHeader)) + i*uint32(unsafe.Sizeof(*sectionDesc))
957 sectionDesc = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[offset]))
958 for j := uint32(0); j < sectionDesc.number; j++ {
959 offset = request.header.outputDesc.offset + sectionDesc.offset + j*sectionDesc.length
960 sections = append(sections, (*uint64)(unsafe.Pointer(&responseBuffer[offset])))
961 }
962 }
963
964 // Find nwmTCPStatsEntry in returned entries
965 var tcpStats *nwmTCPStatsEntry = nil
966 for _, ptr := range sections {
967 switch *ptr {
968 case nwmTCPStatsIdentifier:
969 if tcpStats != nil {
970 return nil, errnoErr(EINVAL)
971 }
972 tcpStats = (*nwmTCPStatsEntry)(unsafe.Pointer(ptr))
973 case nwmIPStatsIdentifier:
974 case nwmIPGStatsIdentifier:
975 case nwmUDPStatsIdentifier:
976 case nwmICMPGStatsEntry:
977 case nwmICMPTStatsEntry:
978 default:
979 return nil, errnoErr(EINVAL)
980 }
981 }
982 if tcpStats == nil {
983 return nil, errnoErr(EINVAL)
984 }
985
986 // GetConnectionDetail EZBNMIF4 call
987 responseBuffer = [4096]byte{0}
988 dsa = [18]uint64{0}
989 bufferAlet, reasonCode = 0, 0
990 bufferLen, returnValue, returnCode = 4096, 0, 0
991 nameptr := (*uint32)(unsafe.Pointer(uintptr(0x21c))) // Get jobname of current process
992 nameptr = (*uint32)(unsafe.Pointer(uintptr(*nameptr + 12)))
993 argv[0] = unsafe.Pointer(uintptr(*nameptr))
994
995 request.header.ident = nwmHeaderIdentifier
996 request.header.length = uint32(unsafe.Sizeof(request.header))
997 request.header.version = nwmCurrentVer
998 request.header.nwmType = nwmTCPConnType
999 request.header.options = 0x80000000
1000
1001 request.filter.ident = nwmFilterIdentifier
1002
1003 var localSockaddr RawSockaddrAny
1004 socklen := _Socklen(SizeofSockaddrAny)
1005 err := getsockname(fd, &localSockaddr, &socklen)
1006 if err != nil {
1007 return nil, errnoErr(EINVAL)
1008 }
1009 if localSockaddr.Addr.Family == AF_INET {
1010 localSockaddr := (*RawSockaddrInet4)(unsafe.Pointer(&localSockaddr.Addr))
1011 localSockFilter := (*RawSockaddrInet4)(unsafe.Pointer(&request.filter.local[0]))
1012 localSockFilter.Family = AF_INET
1013 var i int
1014 for i = 0; i < 4; i++ {
1015 if localSockaddr.Addr[i] != 0 {
1016 break
1017 }
1018 }
1019 if i != 4 {
1020 request.filter.flags |= nwmFilterLclAddrMask
1021 for i = 0; i < 4; i++ {
1022 localSockFilter.Addr[i] = localSockaddr.Addr[i]
1023 }
1024 }
1025 if localSockaddr.Port != 0 {
1026 request.filter.flags |= nwmFilterLclPortMask
1027 localSockFilter.Port = localSockaddr.Port
1028 }
1029 } else if localSockaddr.Addr.Family == AF_INET6 {
1030 localSockaddr := (*RawSockaddrInet6)(unsafe.Pointer(&localSockaddr.Addr))
1031 localSockFilter := (*RawSockaddrInet6)(unsafe.Pointer(&request.filter.local[0]))
1032 localSockFilter.Family = AF_INET6
1033 var i int
1034 for i = 0; i < 16; i++ {
1035 if localSockaddr.Addr[i] != 0 {
1036 break
1037 }
1038 }
1039 if i != 16 {
1040 request.filter.flags |= nwmFilterLclAddrMask
1041 for i = 0; i < 16; i++ {
1042 localSockFilter.Addr[i] = localSockaddr.Addr[i]
1043 }
1044 }
1045 if localSockaddr.Port != 0 {
1046 request.filter.flags |= nwmFilterLclPortMask
1047 localSockFilter.Port = localSockaddr.Port
1048 }
1049 }
1050
1051 svcCall(EZBNMIF4, &argv[0], &dsa[0])
1052
1053 // outputDesc field is filled by EZBNMIF4 on success
1054 if returnCode != 0 || request.header.outputDesc.offset == 0 {
1055 return nil, errnoErr(EINVAL)
1056 }
1057
1058 // Check that EZBNMIF4 returned a nwmConnEntry
1059 conn := (*nwmConnEntry)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
1060 if conn.ident != nwmTCPConnIdentifier {
1061 return nil, errnoErr(EINVAL)
1062 }
1063
1064 // Copy data from the returned data structures into tcpInfo
1065 // Stats from nwmConnEntry are specific to that connection.
1066 // Stats from nwmTCPStatsEntry are global (to the interface?)
1067 // Fields may not be an exact match. Some fields have no equivalent.
1068 var tcpinfo TCPInfo
1069 tcpinfo.State = uint8(conn.state)
1070 tcpinfo.Ca_state = 0 // dummy
1071 tcpinfo.Retransmits = uint8(tcpStats.retransSegs)
1072 tcpinfo.Probes = uint8(tcpStats.outWinProbes)
1073 tcpinfo.Backoff = 0 // dummy
1074 tcpinfo.Options = 0 // dummy
1075 tcpinfo.Rto = tcpStats.retransTimeouts
1076 tcpinfo.Ato = tcpStats.outDelayAcks
1077 tcpinfo.Snd_mss = conn.sendMSS
1078 tcpinfo.Rcv_mss = conn.sendMSS // dummy
1079 tcpinfo.Unacked = 0 // dummy
1080 tcpinfo.Sacked = 0 // dummy
1081 tcpinfo.Lost = 0 // dummy
1082 tcpinfo.Retrans = conn.reXmtCount
1083 tcpinfo.Fackets = 0 // dummy
1084 tcpinfo.Last_data_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.lastActivity[0])))
1085 tcpinfo.Last_ack_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.outOldestTime[0])))
1086 tcpinfo.Last_data_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
1087 tcpinfo.Last_ack_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
1088 tcpinfo.Pmtu = conn.sendMSS // dummy, NWMIfRouteMtu is a candidate
1089 tcpinfo.Rcv_ssthresh = conn.ssThresh
1090 tcpinfo.Rtt = conn.roundTripTime
1091 tcpinfo.Rttvar = conn.roundTripVar
1092 tcpinfo.Snd_ssthresh = conn.ssThresh // dummy
1093 tcpinfo.Snd_cwnd = conn.congestionWnd
1094 tcpinfo.Advmss = conn.sendMSS // dummy
1095 tcpinfo.Reordering = 0 // dummy
1096 tcpinfo.Rcv_rtt = conn.roundTripTime // dummy
1097 tcpinfo.Rcv_space = conn.sendMSS // dummy
1098 tcpinfo.Total_retrans = conn.reXmtCount
1099
1100 svcUnload(&svcNameTable[svc_EZBNMIF4][0], EZBNMIF4)
1101
1102 return &tcpinfo, nil
1103}
1104
1105// GetsockoptString returns the string value of the socket option opt for the
1106// socket associated with fd at the given socket level.
1107func GetsockoptString(fd, level, opt int) (string, error) {
1108 buf := make([]byte, 256)
1109 vallen := _Socklen(len(buf))
1110 err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
1111 if err != nil {
1112 return "", err
1113 }
1114
1115 return string(buf[:vallen-1]), nil
1116}
1117
1118func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
1119 var msg Msghdr
1120 var rsa RawSockaddrAny
1121 msg.Name = (*byte)(unsafe.Pointer(&rsa))
1122 msg.Namelen = SizeofSockaddrAny
1123 var iov Iovec
1124 if len(p) > 0 {
1125 iov.Base = (*byte)(unsafe.Pointer(&p[0]))
1126 iov.SetLen(len(p))
1127 }
1128 var dummy byte
1129 if len(oob) > 0 {
1130 // receive at least one normal byte
1131 if len(p) == 0 {
1132 iov.Base = &dummy
1133 iov.SetLen(1)
1134 }
1135 msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
1136 msg.SetControllen(len(oob))
1137 }
1138 msg.Iov = &iov
1139 msg.Iovlen = 1
1140 if n, err = recvmsg(fd, &msg, flags); err != nil {
1141 return
1142 }
1143 oobn = int(msg.Controllen)
1144 recvflags = int(msg.Flags)
1145 // source address is only specified if the socket is unconnected
1146 if rsa.Addr.Family != AF_UNSPEC {
1147 // TODO(neeilan): Remove 0 arg added to get this compiling on z/OS
1148 from, err = anyToSockaddr(0, &rsa)
1149 }
1150 return
1151}
1152
1153func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
1154 _, err = SendmsgN(fd, p, oob, to, flags)
1155 return
1156}
1157
1158func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
1159 var ptr unsafe.Pointer
1160 var salen _Socklen
1161 if to != nil {
1162 var err error
1163 ptr, salen, err = to.sockaddr()
1164 if err != nil {
1165 return 0, err
1166 }
1167 }
1168 var msg Msghdr
1169 msg.Name = (*byte)(unsafe.Pointer(ptr))
1170 msg.Namelen = int32(salen)
1171 var iov Iovec
1172 if len(p) > 0 {
1173 iov.Base = (*byte)(unsafe.Pointer(&p[0]))
1174 iov.SetLen(len(p))
1175 }
1176 var dummy byte
1177 if len(oob) > 0 {
1178 // send at least one normal byte
1179 if len(p) == 0 {
1180 iov.Base = &dummy
1181 iov.SetLen(1)
1182 }
1183 msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
1184 msg.SetControllen(len(oob))
1185 }
1186 msg.Iov = &iov
1187 msg.Iovlen = 1
1188 if n, err = sendmsg(fd, &msg, flags); err != nil {
1189 return 0, err
1190 }
1191 if len(oob) > 0 && len(p) == 0 {
1192 n = 0
1193 }
1194 return n, nil
1195}
1196
1197func Opendir(name string) (uintptr, error) {
1198 p, err := BytePtrFromString(name)
1199 if err != nil {
1200 return 0, err
1201 }
1202 dir, _, e := syscall_syscall(SYS___OPENDIR_A, uintptr(unsafe.Pointer(p)), 0, 0)
1203 runtime.KeepAlive(unsafe.Pointer(p))
1204 if e != 0 {
1205 err = errnoErr(e)
1206 }
1207 return dir, err
1208}
1209
1210// clearsyscall.Errno resets the errno value to 0.
1211func clearErrno()
1212
1213func Readdir(dir uintptr) (*Dirent, error) {
1214 var ent Dirent
1215 var res uintptr
1216 // __readdir_r_a returns errno at the end of the directory stream, rather than 0.
1217 // Therefore to avoid false positives we clear errno before calling it.
1218
1219 // TODO(neeilan): Commented this out to get sys/unix compiling on z/OS. Uncomment and fix. Error: "undefined: clearsyscall"
1220 //clearsyscall.Errno() // TODO(mundaym): check pre-emption rules.
1221
1222 e, _, _ := syscall_syscall(SYS___READDIR_R_A, dir, uintptr(unsafe.Pointer(&ent)), uintptr(unsafe.Pointer(&res)))
1223 var err error
1224 if e != 0 {
1225 err = errnoErr(Errno(e))
1226 }
1227 if res == 0 {
1228 return nil, err
1229 }
1230 return &ent, err
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}