256
|
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 |
|
|
8 |
package unix |
|
9 |
|
|
10 |
import ( |
|
11 |
"bytes" |
|
12 |
"runtime" |
|
13 |
"sort" |
|
14 |
"sync" |
|
15 |
"syscall" |
|
16 |
"unsafe" |
|
17 |
) |
|
18 |
|
|
19 |
const ( |
|
20 |
O_CLOEXEC = 0 // Dummy value (not supported). |
|
21 |
AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX |
|
22 |
) |
|
23 |
|
|
24 |
func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) |
|
25 |
func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) |
|
26 |
func syscall_syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) |
|
27 |
func syscall_rawsyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) |
|
28 |
func syscall_syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) |
|
29 |
func syscall_rawsyscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) |
|
30 |
|
|
31 |
func 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 |
|
|
50 |
func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64) |
|
51 |
func svcLoad(name *byte) unsafe.Pointer |
|
52 |
func svcUnload(name *byte, fnptr unsafe.Pointer) int64 |
|
53 |
|
|
54 |
func (d *Dirent) NameString() string { |
|
55 |
if d == nil { |
|
56 |
return "" |
|
57 |
} |
|
58 |
return string(d.Name[:d.Namlen]) |
|
59 |
} |
|
60 |
|
|
61 |
func (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) |
260
|
70 |
sa.raw.Addr = sa.Addr |
256
|
71 |
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil |
|
72 |
} |
|
73 |
|
|
74 |
func (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 |
260
|
84 |
sa.raw.Addr = sa.Addr |
256
|
85 |
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil |
|
86 |
} |
|
87 |
|
|
88 |
func (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 |
|
|
102 |
func 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]) |
260
|
143 |
sa.Addr = pp.Addr |
256
|
144 |
return sa, nil |
|
145 |
|
|
146 |
case AF_INET6: |
|
147 |
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) |
|
148 |
sa := new(SockaddrInet6) |
|
149 |
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) |
|
150 |
sa.Port = int(p[0])<<8 + int(p[1]) |
|
151 |
sa.ZoneId = pp.Scope_id |
260
|
152 |
sa.Addr = pp.Addr |
256
|
153 |
return sa, nil |
|
154 |
} |
|
155 |
return nil, EAFNOSUPPORT |
|
156 |
} |
|
157 |
|
|
158 |
func 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 |
|
|
174 |
func (iov *Iovec) SetLen(length int) { |
|
175 |
iov.Len = uint64(length) |
|
176 |
} |
|
177 |
|
|
178 |
func (msghdr *Msghdr) SetControllen(length int) { |
|
179 |
msghdr.Controllen = int32(length) |
|
180 |
} |
|
181 |
|
|
182 |
func (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 |
|
|
226 |
func 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 |
|
|
250 |
func 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 |
|
|
259 |
func 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 |
|
|
268 |
func 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 |
|
|
280 |
var 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 |
|
287 |
func Madvise(b []byte, advice int) (err error) { |
|
288 |
return |
|
289 |
} |
|
290 |
|
|
291 |
func 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 |
|
|
295 |
func 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 |
|
|
306 |
func 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 |
|
|
317 |
func 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 |
|
|
336 |
func 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 |
|
|
363 |
func 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 |
|
|
381 |
func Open(path string, mode int, perm uint32) (fd int, err error) { |
|
382 |
return open(path, mode, perm) |
|
383 |
} |
|
384 |
|
|
385 |
func 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 |
|
|
401 |
func Remove(path string) error { |
|
402 |
return remove(path) |
|
403 |
} |
|
404 |
|
|
405 |
const ImplementsGetwd = true |
|
406 |
|
|
407 |
func 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 |
|
|
422 |
func 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 |
|
|
435 |
func 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 |
|
|
461 |
func 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 |
|
|
473 |
func gettid() uint64 |
|
474 |
|
|
475 |
func Gettid() (tid int) { |
|
476 |
return int(gettid()) |
|
477 |
} |
|
478 |
|
|
479 |
type 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 |
|
|
490 |
const ( |
|
491 |
mask = 0x7F |
|
492 |
core = 0x80 |
|
493 |
exited = 0x00 |
|
494 |
stopped = 0x7F |
|
495 |
shift = 8 |
|
496 |
) |
|
497 |
|
|
498 |
func (w WaitStatus) Exited() bool { return w&mask == exited } |
|
499 |
|
|
500 |
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited } |
|
501 |
|
|
502 |
func (w WaitStatus) Stopped() bool { return w&0xFF == stopped } |
|
503 |
|
|
504 |
func (w WaitStatus) Continued() bool { return w == 0xFFFF } |
|
505 |
|
|
506 |
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } |
|
507 |
|
|
508 |
func (w WaitStatus) ExitStatus() int { |
|
509 |
if !w.Exited() { |
|
510 |
return -1 |
|
511 |
} |
|
512 |
return int(w>>shift) & 0xFF |
|
513 |
} |
|
514 |
|
|
515 |
func (w WaitStatus) Signal() Signal { |
|
516 |
if !w.Signaled() { |
|
517 |
return -1 |
|
518 |
} |
|
519 |
return Signal(w & mask) |
|
520 |
} |
|
521 |
|
|
522 |
func (w WaitStatus) StopSignal() Signal { |
|
523 |
if !w.Stopped() { |
|
524 |
return -1 |
|
525 |
} |
|
526 |
return Signal(w>>shift) & 0xFF |
|
527 |
} |
|
528 |
|
|
529 |
func (w WaitStatus) TrapCause() int { return -1 } |
|
530 |
|
|
531 |
//sys waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) |
|
532 |
|
|
533 |
func 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 |
|
|
546 |
func 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 |
|
|
554 |
func 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 |
|
|
566 |
func setTimespec(sec, nsec int64) Timespec { |
|
567 |
return Timespec{Sec: sec, Nsec: nsec} |
|
568 |
} |
|
569 |
|
|
570 |
func 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 |
|
|
576 |
func Pipe(p []int) (err error) { |
|
577 |
if len(p) != 2 { |
|
578 |
return EINVAL |
|
579 |
} |
|
580 |
var pp [2]_C_int |
|
581 |
err = pipe(&pp) |
260
|
582 |
if err == nil { |
|
583 |
p[0] = int(pp[0]) |
|
584 |
p[1] = int(pp[1]) |
|
585 |
} |
256
|
586 |
return |
|
587 |
} |
|
588 |
|
|
589 |
//sys utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A |
|
590 |
|
|
591 |
func 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 |
|
|
598 |
func 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 |
|
|
611 |
func 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 |
|
|
621 |
const ( |
|
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 |
|
|
678 |
type nwmTriplet struct { |
|
679 |
offset uint32 |
|
680 |
length uint32 |
|
681 |
number uint32 |
|
682 |
} |
|
683 |
|
|
684 |
type nwmQuadruplet struct { |
|
685 |
offset uint32 |
|
686 |
length uint32 |
|
687 |
number uint32 |
|
688 |
match uint32 |
|
689 |
} |
|
690 |
|
|
691 |
type 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 |
|
|
703 |
type 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 |
|
|
736 |
type nwmRecHeader struct { |
|
737 |
ident uint32 |
|
738 |
length uint32 |
|
739 |
number byte |
|
740 |
_ [3]byte |
|
741 |
} |
|
742 |
|
|
743 |
type 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 |
|
|
821 |
type 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 |
|
|
898 |
var svcNameTable [][]byte = [][]byte{ |
|
899 |
[]byte("\xc5\xe9\xc2\xd5\xd4\xc9\xc6\xf4"), // svc_EZBNMIF4 |
|
900 |
} |
|
901 |
|
|
902 |
const ( |
|
903 |
svc_EZBNMIF4 = 0 |
|
904 |
) |
|
905 |
|
|
906 |
func 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. |
|
1107 |
func 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 |
|
|
1118 |
func 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 |
|
|
1153 |
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { |
|
1154 |
_, err = SendmsgN(fd, p, oob, to, flags) |
|
1155 |
return |
|
1156 |
} |
|
1157 |
|
|
1158 |
func 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 |
|
|
1197 |
func 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. |
|
1211 |
func clearErrno() |
|
1212 |
|
|
1213 |
func 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 |
|
|
1233 |
func 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 |
|
|
1241 |
func Seekdir(dir uintptr, pos int) { |
|
1242 |
_, _, _ = syscall_syscall(SYS_SEEKDIR, dir, uintptr(pos), 0) |
|
1243 |
} |
|
1244 |
|
|
1245 |
func 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. |
|
1255 |
func 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 |
|
|
1276 |
func 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 |
|
|
1309 |
func 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 |
|
|
1317 |
func 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 |
|
|
1325 |
func 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 |
|
|
1333 |
func 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 |
|
|
1341 |
func 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 |
|
|
1349 |
func 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 |
|
|
1375 |
func 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 |
|
|
1384 |
var ( |
|
1385 |
Stdin = 0 |
|
1386 |
Stdout = 1 |
|
1387 |
Stderr = 2 |
|
1388 |
) |
|
1389 |
|
|
1390 |
// Do the interface allocations only once for common |
|
1391 |
// Errno values. |
|
1392 |
var ( |
|
1393 |
errEAGAIN error = syscall.EAGAIN |
|
1394 |
errEINVAL error = syscall.EINVAL |
|
1395 |
errENOENT error = syscall.ENOENT |
|
1396 |
) |
|
1397 |
|
|
1398 |
var ( |
|
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. |
|
1405 |
func 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. |
|
1420 |
func 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. |
|
1431 |
func 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". |
|
1444 |
func 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. |
|
1455 |
func 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 |
|
|
1465 |
type 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 |
|
|
1472 |
func (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 |
|
|
1501 |
func (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 |
|
|
1523 |
func 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 |
|
|
1536 |
func 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. |
|
1549 |
var SocketDisableIPv6 bool |
|
1550 |
|
|
1551 |
// Sockaddr represents a socket address. |
|
1552 |
type 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. |
|
1557 |
type 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. |
|
1564 |
type 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. |
|
1572 |
type SockaddrUnix struct { |
|
1573 |
Name string |
|
1574 |
raw RawSockaddrUnix |
|
1575 |
} |
|
1576 |
|
|
1577 |
func 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 |
|
|
1585 |
func 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 |
|
|
1593 |
func 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 |
|
|
1602 |
func 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 |
|
|
1609 |
func 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 |
|
|
1616 |
func 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 |
|
|
1622 |
func 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 |
|
|
1629 |
func 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 |
|
|
1636 |
func 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 |
|
|
1643 |
func 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 |
|
|
1650 |
func 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 |
|
|
1657 |
func 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 |
|
|
1664 |
func 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 |
|
|
1671 |
func 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 |
|
|
1683 |
func 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 |
|
|
1691 |
func SetsockoptByte(fd, level, opt int, value byte) (err error) { |
|
1692 |
return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1) |
|
1693 |
} |
|
1694 |
|
|
1695 |
func 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 |
|
|
1700 |
func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) { |
|
1701 |
return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4) |
|
1702 |
} |
|
1703 |
|
|
1704 |
func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) { |
|
1705 |
return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq) |
|
1706 |
} |
|
1707 |
|
|
1708 |
func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) { |
|
1709 |
return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq) |
|
1710 |
} |
|
1711 |
|
|
1712 |
func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error { |
|
1713 |
return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter) |
|
1714 |
} |
|
1715 |
|
|
1716 |
func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) { |
|
1717 |
return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger) |
|
1718 |
} |
|
1719 |
|
|
1720 |
func 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 |
|
|
1728 |
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) { |
|
1729 |
return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv)) |
|
1730 |
} |
|
1731 |
|
|
1732 |
func SetsockoptUint64(fd, level, opt int, value uint64) (err error) { |
|
1733 |
return setsockopt(fd, level, opt, unsafe.Pointer(&value), 8) |
|
1734 |
} |
|
1735 |
|
|
1736 |
func 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 |
|
|
1744 |
func 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 |
|
|
1754 |
var ioSync int64 |
|
1755 |
|
|
1756 |
func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) } |
|
1757 |
|
|
1758 |
func 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"]). |
|
1777 |
func Exec(argv0 string, argv []string, envv []string) error { |
|
1778 |
return syscall.Exec(argv0, argv, envv) |
|
1779 |
} |
|
1780 |
|
|
1781 |
func 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 |
|
|
1790 |
func 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 |
} |