cubefs

Форк
0
/x
/
syscall_zos_s390x.go 
1994 строки · 53.3 Кб
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
	"fmt"
13
	"runtime"
14
	"sort"
15
	"strings"
16
	"sync"
17
	"syscall"
18
	"unsafe"
19
)
20

21
const (
22
	O_CLOEXEC = 0       // Dummy value (not supported).
23
	AF_LOCAL  = AF_UNIX // AF_LOCAL is an alias for AF_UNIX
24
)
25

26
func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
27
func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
28
func syscall_syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
29
func syscall_rawsyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
30
func syscall_syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
31
func syscall_rawsyscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
32

33
func copyStat(stat *Stat_t, statLE *Stat_LE_t) {
34
	stat.Dev = uint64(statLE.Dev)
35
	stat.Ino = uint64(statLE.Ino)
36
	stat.Nlink = uint64(statLE.Nlink)
37
	stat.Mode = uint32(statLE.Mode)
38
	stat.Uid = uint32(statLE.Uid)
39
	stat.Gid = uint32(statLE.Gid)
40
	stat.Rdev = uint64(statLE.Rdev)
41
	stat.Size = statLE.Size
42
	stat.Atim.Sec = int64(statLE.Atim)
43
	stat.Atim.Nsec = 0 //zos doesn't return nanoseconds
44
	stat.Mtim.Sec = int64(statLE.Mtim)
45
	stat.Mtim.Nsec = 0 //zos doesn't return nanoseconds
46
	stat.Ctim.Sec = int64(statLE.Ctim)
47
	stat.Ctim.Nsec = 0 //zos doesn't return nanoseconds
48
	stat.Blksize = int64(statLE.Blksize)
49
	stat.Blocks = statLE.Blocks
50
}
51

52
func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
53
func svcLoad(name *byte) unsafe.Pointer
54
func svcUnload(name *byte, fnptr unsafe.Pointer) int64
55

56
func (d *Dirent) NameString() string {
57
	if d == nil {
58
		return ""
59
	}
60
	s := string(d.Name[:])
61
	idx := strings.IndexByte(s, 0)
62
	if idx == -1 {
63
		return s
64
	} else {
65
		return s[:idx]
66
	}
67
}
68

69
func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
70
	if sa.Port < 0 || sa.Port > 0xFFFF {
71
		return nil, 0, EINVAL
72
	}
73
	sa.raw.Len = SizeofSockaddrInet4
74
	sa.raw.Family = AF_INET
75
	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
76
	p[0] = byte(sa.Port >> 8)
77
	p[1] = byte(sa.Port)
78
	sa.raw.Addr = sa.Addr
79
	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
80
}
81

82
func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
83
	if sa.Port < 0 || sa.Port > 0xFFFF {
84
		return nil, 0, EINVAL
85
	}
86
	sa.raw.Len = SizeofSockaddrInet6
87
	sa.raw.Family = AF_INET6
88
	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
89
	p[0] = byte(sa.Port >> 8)
90
	p[1] = byte(sa.Port)
91
	sa.raw.Scope_id = sa.ZoneId
92
	sa.raw.Addr = sa.Addr
93
	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
94
}
95

96
func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
97
	name := sa.Name
98
	n := len(name)
99
	if n >= len(sa.raw.Path) || n == 0 {
100
		return nil, 0, EINVAL
101
	}
102
	sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
103
	sa.raw.Family = AF_UNIX
104
	for i := 0; i < n; i++ {
105
		sa.raw.Path[i] = int8(name[i])
106
	}
107
	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
108
}
109

110
func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) {
111
	// TODO(neeilan): Implement use of first param (fd)
112
	switch rsa.Addr.Family {
113
	case AF_UNIX:
114
		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
115
		sa := new(SockaddrUnix)
116
		// For z/OS, only replace NUL with @ when the
117
		// length is not zero.
118
		if pp.Len != 0 && pp.Path[0] == 0 {
119
			// "Abstract" Unix domain socket.
120
			// Rewrite leading NUL as @ for textual display.
121
			// (This is the standard convention.)
122
			// Not friendly to overwrite in place,
123
			// but the callers below don't care.
124
			pp.Path[0] = '@'
125
		}
126

127
		// Assume path ends at NUL.
128
		//
129
		// For z/OS, the length of the name is a field
130
		// in the structure. To be on the safe side, we
131
		// will still scan the name for a NUL but only
132
		// to the length provided in the structure.
133
		//
134
		// This is not technically the Linux semantics for
135
		// abstract Unix domain sockets--they are supposed
136
		// to be uninterpreted fixed-size binary blobs--but
137
		// everyone uses this convention.
138
		n := 0
139
		for n < int(pp.Len) && pp.Path[n] != 0 {
140
			n++
141
		}
142
		sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
143
		return sa, nil
144

145
	case AF_INET:
146
		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
147
		sa := new(SockaddrInet4)
148
		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
149
		sa.Port = int(p[0])<<8 + int(p[1])
150
		sa.Addr = pp.Addr
151
		return sa, nil
152

153
	case AF_INET6:
154
		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
155
		sa := new(SockaddrInet6)
156
		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
157
		sa.Port = int(p[0])<<8 + int(p[1])
158
		sa.ZoneId = pp.Scope_id
159
		sa.Addr = pp.Addr
160
		return sa, nil
161
	}
162
	return nil, EAFNOSUPPORT
163
}
164

165
func Accept(fd int) (nfd int, sa Sockaddr, err error) {
166
	var rsa RawSockaddrAny
167
	var len _Socklen = SizeofSockaddrAny
168
	nfd, err = accept(fd, &rsa, &len)
169
	if err != nil {
170
		return
171
	}
172
	// TODO(neeilan): Remove 0 in call
173
	sa, err = anyToSockaddr(0, &rsa)
174
	if err != nil {
175
		Close(nfd)
176
		nfd = 0
177
	}
178
	return
179
}
180

181
func (iov *Iovec) SetLen(length int) {
182
	iov.Len = uint64(length)
183
}
184

185
func (msghdr *Msghdr) SetControllen(length int) {
186
	msghdr.Controllen = int32(length)
187
}
188

189
func (cmsg *Cmsghdr) SetLen(length int) {
190
	cmsg.Len = int32(length)
191
}
192

193
//sys   fcntl(fd int, cmd int, arg int) (val int, err error)
194
//sys	read(fd int, p []byte) (n int, err error)
195
//sys   readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
196
//sys	write(fd int, p []byte) (n int, err error)
197

198
//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = SYS___ACCEPT_A
199
//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___BIND_A
200
//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___CONNECT_A
201
//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
202
//sysnb	setgroups(n int, list *_Gid_t) (err error)
203
//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
204
//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
205
//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
206
//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
207
//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETPEERNAME_A
208
//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETSOCKNAME_A
209
//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = SYS___RECVFROM_A
210
//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = SYS___SENDTO_A
211
//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___RECVMSG_A
212
//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___SENDMSG_A
213
//sys   mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) = SYS_MMAP
214
//sys   munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP
215
//sys   ioctl(fd int, req int, arg uintptr) (err error) = SYS_IOCTL
216
//sys   ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = SYS_IOCTL
217

218
//sys   Access(path string, mode uint32) (err error) = SYS___ACCESS_A
219
//sys   Chdir(path string) (err error) = SYS___CHDIR_A
220
//sys	Chown(path string, uid int, gid int) (err error) = SYS___CHOWN_A
221
//sys	Chmod(path string, mode uint32) (err error) = SYS___CHMOD_A
222
//sys   Creat(path string, mode uint32) (fd int, err error) = SYS___CREAT_A
223
//sys	Dup(oldfd int) (fd int, err error)
224
//sys	Dup2(oldfd int, newfd int) (err error)
225
//sys	Errno2() (er2 int) = SYS___ERRNO2
226
//sys	Err2ad() (eadd *int) = SYS___ERR2AD
227
//sys	Exit(code int)
228
//sys	Fchdir(fd int) (err error)
229
//sys	Fchmod(fd int, mode uint32) (err error)
230
//sys	Fchown(fd int, uid int, gid int) (err error)
231
//sys	FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) = SYS_FCNTL
232
//sys	fstat(fd int, stat *Stat_LE_t) (err error)
233

234
func Fstat(fd int, stat *Stat_t) (err error) {
235
	var statLE Stat_LE_t
236
	err = fstat(fd, &statLE)
237
	copyStat(stat, &statLE)
238
	return
239
}
240

241
//sys	Fstatvfs(fd int, stat *Statvfs_t) (err error) = SYS_FSTATVFS
242
//sys	Fsync(fd int) (err error)
243
//sys	Ftruncate(fd int, length int64) (err error)
244
//sys   Getpagesize() (pgsize int) = SYS_GETPAGESIZE
245
//sys   Mprotect(b []byte, prot int) (err error) = SYS_MPROTECT
246
//sys   Msync(b []byte, flags int) (err error) = SYS_MSYNC
247
//sys   Poll(fds []PollFd, timeout int) (n int, err error) = SYS_POLL
248
//sys   Times(tms *Tms) (ticks uintptr, err error) = SYS_TIMES
249
//sys   W_Getmntent(buff *byte, size int) (lastsys int, err error) = SYS_W_GETMNTENT
250
//sys   W_Getmntent_A(buff *byte, size int) (lastsys int, err error) = SYS___W_GETMNTENT_A
251

252
//sys   mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) = SYS___MOUNT_A
253
//sys   unmount(filesystem string, mtm int) (err error) = SYS___UMOUNT_A
254
//sys   Chroot(path string) (err error) = SYS___CHROOT_A
255
//sys   Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) = SYS_SELECT
256
//sysnb Uname(buf *Utsname) (err error) = SYS___UNAME_A
257

258
func Ptsname(fd int) (name string, err error) {
259
	r0, _, e1 := syscall_syscall(SYS___PTSNAME_A, uintptr(fd), 0, 0)
260
	name = u2s(unsafe.Pointer(r0))
261
	if e1 != 0 {
262
		err = errnoErr(e1)
263
	}
264
	return
265
}
266

267
func u2s(cstr unsafe.Pointer) string {
268
	str := (*[1024]uint8)(cstr)
269
	i := 0
270
	for str[i] != 0 {
271
		i++
272
	}
273
	return string(str[:i])
274
}
275

276
func Close(fd int) (err error) {
277
	_, _, e1 := syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0)
278
	for i := 0; e1 == EAGAIN && i < 10; i++ {
279
		_, _, _ = syscall_syscall(SYS_USLEEP, uintptr(10), 0, 0)
280
		_, _, e1 = syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0)
281
	}
282
	if e1 != 0 {
283
		err = errnoErr(e1)
284
	}
285
	return
286
}
287

288
var mapper = &mmapper{
289
	active: make(map[*byte][]byte),
290
	mmap:   mmap,
291
	munmap: munmap,
292
}
293

294
// Dummy function: there are no semantics for Madvise on z/OS
295
func Madvise(b []byte, advice int) (err error) {
296
	return
297
}
298

299
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
300
	return mapper.Mmap(fd, offset, length, prot, flags)
301
}
302

303
func Munmap(b []byte) (err error) {
304
	return mapper.Munmap(b)
305
}
306

307
//sys   Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A
308
//sysnb	Getegid() (egid int)
309
//sysnb	Geteuid() (uid int)
310
//sysnb	Getgid() (gid int)
311
//sysnb	Getpid() (pid int)
312
//sysnb	Getpgid(pid int) (pgid int, err error) = SYS_GETPGID
313

314
func Getpgrp() (pid int) {
315
	pid, _ = Getpgid(0)
316
	return
317
}
318

319
//sysnb	Getppid() (pid int)
320
//sys	Getpriority(which int, who int) (prio int, err error)
321
//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_GETRLIMIT
322

323
//sysnb getrusage(who int, rusage *rusage_zos) (err error) = SYS_GETRUSAGE
324

325
func Getrusage(who int, rusage *Rusage) (err error) {
326
	var ruz rusage_zos
327
	err = getrusage(who, &ruz)
328
	//Only the first two fields of Rusage are set
329
	rusage.Utime.Sec = ruz.Utime.Sec
330
	rusage.Utime.Usec = int64(ruz.Utime.Usec)
331
	rusage.Stime.Sec = ruz.Stime.Sec
332
	rusage.Stime.Usec = int64(ruz.Stime.Usec)
333
	return
334
}
335

336
//sysnb Getsid(pid int) (sid int, err error) = SYS_GETSID
337
//sysnb	Getuid() (uid int)
338
//sysnb	Kill(pid int, sig Signal) (err error)
339
//sys	Lchown(path string, uid int, gid int) (err error) = SYS___LCHOWN_A
340
//sys	Link(path string, link string) (err error) = SYS___LINK_A
341
//sys	Listen(s int, n int) (err error)
342
//sys	lstat(path string, stat *Stat_LE_t) (err error) = SYS___LSTAT_A
343

344
func Lstat(path string, stat *Stat_t) (err error) {
345
	var statLE Stat_LE_t
346
	err = lstat(path, &statLE)
347
	copyStat(stat, &statLE)
348
	return
349
}
350

351
//sys	Mkdir(path string, mode uint32) (err error) = SYS___MKDIR_A
352
//sys   Mkfifo(path string, mode uint32) (err error) = SYS___MKFIFO_A
353
//sys	Mknod(path string, mode uint32, dev int) (err error) = SYS___MKNOD_A
354
//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
355
//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
356
//sys	Readlink(path string, buf []byte) (n int, err error) = SYS___READLINK_A
357
//sys	Rename(from string, to string) (err error) = SYS___RENAME_A
358
//sys	Rmdir(path string) (err error) = SYS___RMDIR_A
359
//sys   Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
360
//sys	Setpriority(which int, who int, prio int) (err error)
361
//sysnb	Setpgid(pid int, pgid int) (err error) = SYS_SETPGID
362
//sysnb	Setrlimit(resource int, lim *Rlimit) (err error)
363
//sysnb	Setregid(rgid int, egid int) (err error) = SYS_SETREGID
364
//sysnb	Setreuid(ruid int, euid int) (err error) = SYS_SETREUID
365
//sysnb	Setsid() (pid int, err error) = SYS_SETSID
366
//sys	Setuid(uid int) (err error) = SYS_SETUID
367
//sys	Setgid(uid int) (err error) = SYS_SETGID
368
//sys	Shutdown(fd int, how int) (err error)
369
//sys	stat(path string, statLE *Stat_LE_t) (err error) = SYS___STAT_A
370

371
func Stat(path string, sta *Stat_t) (err error) {
372
	var statLE Stat_LE_t
373
	err = stat(path, &statLE)
374
	copyStat(sta, &statLE)
375
	return
376
}
377

378
//sys	Symlink(path string, link string) (err error) = SYS___SYMLINK_A
379
//sys	Sync() = SYS_SYNC
380
//sys	Truncate(path string, length int64) (err error) = SYS___TRUNCATE_A
381
//sys	Tcgetattr(fildes int, termptr *Termios) (err error) = SYS_TCGETATTR
382
//sys	Tcsetattr(fildes int, when int, termptr *Termios) (err error) = SYS_TCSETATTR
383
//sys	Umask(mask int) (oldmask int)
384
//sys	Unlink(path string) (err error) = SYS___UNLINK_A
385
//sys	Utime(path string, utim *Utimbuf) (err error) = SYS___UTIME_A
386

387
//sys	open(path string, mode int, perm uint32) (fd int, err error) = SYS___OPEN_A
388

389
func Open(path string, mode int, perm uint32) (fd int, err error) {
390
	return open(path, mode, perm)
391
}
392

393
func Mkfifoat(dirfd int, path string, mode uint32) (err error) {
394
	wd, err := Getwd()
395
	if err != nil {
396
		return err
397
	}
398

399
	if err := Fchdir(dirfd); err != nil {
400
		return err
401
	}
402
	defer Chdir(wd)
403

404
	return Mkfifo(path, mode)
405
}
406

407
//sys	remove(path string) (err error)
408

409
func Remove(path string) error {
410
	return remove(path)
411
}
412

413
const ImplementsGetwd = true
414

415
func Getcwd(buf []byte) (n int, err error) {
416
	var p unsafe.Pointer
417
	if len(buf) > 0 {
418
		p = unsafe.Pointer(&buf[0])
419
	} else {
420
		p = unsafe.Pointer(&_zero)
421
	}
422
	_, _, e := syscall_syscall(SYS___GETCWD_A, uintptr(p), uintptr(len(buf)), 0)
423
	n = clen(buf) + 1
424
	if e != 0 {
425
		err = errnoErr(e)
426
	}
427
	return
428
}
429

430
func Getwd() (wd string, err error) {
431
	var buf [PathMax]byte
432
	n, err := Getcwd(buf[0:])
433
	if err != nil {
434
		return "", err
435
	}
436
	// Getcwd returns the number of bytes written to buf, including the NUL.
437
	if n < 1 || n > len(buf) || buf[n-1] != 0 {
438
		return "", EINVAL
439
	}
440
	return string(buf[0 : n-1]), nil
441
}
442

443
func Getgroups() (gids []int, err error) {
444
	n, err := getgroups(0, nil)
445
	if err != nil {
446
		return nil, err
447
	}
448
	if n == 0 {
449
		return nil, nil
450
	}
451

452
	// Sanity check group count.  Max is 1<<16 on Linux.
453
	if n < 0 || n > 1<<20 {
454
		return nil, EINVAL
455
	}
456

457
	a := make([]_Gid_t, n)
458
	n, err = getgroups(n, &a[0])
459
	if err != nil {
460
		return nil, err
461
	}
462
	gids = make([]int, n)
463
	for i, v := range a[0:n] {
464
		gids[i] = int(v)
465
	}
466
	return
467
}
468

469
func Setgroups(gids []int) (err error) {
470
	if len(gids) == 0 {
471
		return setgroups(0, nil)
472
	}
473

474
	a := make([]_Gid_t, len(gids))
475
	for i, v := range gids {
476
		a[i] = _Gid_t(v)
477
	}
478
	return setgroups(len(a), &a[0])
479
}
480

481
func gettid() uint64
482

483
func Gettid() (tid int) {
484
	return int(gettid())
485
}
486

487
type WaitStatus uint32
488

489
// Wait status is 7 bits at bottom, either 0 (exited),
490
// 0x7F (stopped), or a signal number that caused an exit.
491
// The 0x80 bit is whether there was a core dump.
492
// An extra number (exit code, signal causing a stop)
493
// is in the high bits.  At least that's the idea.
494
// There are various irregularities.  For example, the
495
// "continued" status is 0xFFFF, distinguishing itself
496
// from stopped via the core dump bit.
497

498
const (
499
	mask    = 0x7F
500
	core    = 0x80
501
	exited  = 0x00
502
	stopped = 0x7F
503
	shift   = 8
504
)
505

506
func (w WaitStatus) Exited() bool { return w&mask == exited }
507

508
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited }
509

510
func (w WaitStatus) Stopped() bool { return w&0xFF == stopped }
511

512
func (w WaitStatus) Continued() bool { return w == 0xFFFF }
513

514
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
515

516
func (w WaitStatus) ExitStatus() int {
517
	if !w.Exited() {
518
		return -1
519
	}
520
	return int(w>>shift) & 0xFF
521
}
522

523
func (w WaitStatus) Signal() Signal {
524
	if !w.Signaled() {
525
		return -1
526
	}
527
	return Signal(w & mask)
528
}
529

530
func (w WaitStatus) StopSignal() Signal {
531
	if !w.Stopped() {
532
		return -1
533
	}
534
	return Signal(w>>shift) & 0xFF
535
}
536

537
func (w WaitStatus) TrapCause() int { return -1 }
538

539
//sys	waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error)
540

541
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
542
	// TODO(mundaym): z/OS doesn't have wait4. I don't think getrusage does what we want.
543
	// At the moment rusage will not be touched.
544
	var status _C_int
545
	wpid, err = waitpid(pid, &status, options)
546
	if wstatus != nil {
547
		*wstatus = WaitStatus(status)
548
	}
549
	return
550
}
551

552
//sysnb	gettimeofday(tv *timeval_zos) (err error)
553

554
func Gettimeofday(tv *Timeval) (err error) {
555
	var tvz timeval_zos
556
	err = gettimeofday(&tvz)
557
	tv.Sec = tvz.Sec
558
	tv.Usec = int64(tvz.Usec)
559
	return
560
}
561

562
func Time(t *Time_t) (tt Time_t, err error) {
563
	var tv Timeval
564
	err = Gettimeofday(&tv)
565
	if err != nil {
566
		return 0, err
567
	}
568
	if t != nil {
569
		*t = Time_t(tv.Sec)
570
	}
571
	return Time_t(tv.Sec), nil
572
}
573

574
func setTimespec(sec, nsec int64) Timespec {
575
	return Timespec{Sec: sec, Nsec: nsec}
576
}
577

578
func setTimeval(sec, usec int64) Timeval { //fix
579
	return Timeval{Sec: sec, Usec: usec}
580
}
581

582
//sysnb pipe(p *[2]_C_int) (err error)
583

584
func Pipe(p []int) (err error) {
585
	if len(p) != 2 {
586
		return EINVAL
587
	}
588
	var pp [2]_C_int
589
	err = pipe(&pp)
590
	if err == nil {
591
		p[0] = int(pp[0])
592
		p[1] = int(pp[1])
593
	}
594
	return
595
}
596

597
//sys	utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A
598

599
func Utimes(path string, tv []Timeval) (err error) {
600
	if len(tv) != 2 {
601
		return EINVAL
602
	}
603
	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
604
}
605

606
func UtimesNano(path string, ts []Timespec) error {
607
	if len(ts) != 2 {
608
		return EINVAL
609
	}
610
	// Not as efficient as it could be because Timespec and
611
	// Timeval have different types in the different OSes
612
	tv := [2]Timeval{
613
		NsecToTimeval(TimespecToNsec(ts[0])),
614
		NsecToTimeval(TimespecToNsec(ts[1])),
615
	}
616
	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
617
}
618

619
func Getsockname(fd int) (sa Sockaddr, err error) {
620
	var rsa RawSockaddrAny
621
	var len _Socklen = SizeofSockaddrAny
622
	if err = getsockname(fd, &rsa, &len); err != nil {
623
		return
624
	}
625
	// TODO(neeilan) : Remove this 0 ( added to get sys/unix compiling on z/OS )
626
	return anyToSockaddr(0, &rsa)
627
}
628

629
const (
630
	// identifier constants
631
	nwmHeaderIdentifier    = 0xd5e6d4c8
632
	nwmFilterIdentifier    = 0xd5e6d4c6
633
	nwmTCPConnIdentifier   = 0xd5e6d4c3
634
	nwmRecHeaderIdentifier = 0xd5e6d4d9
635
	nwmIPStatsIdentifier   = 0xd5e6d4c9d7e2e340
636
	nwmIPGStatsIdentifier  = 0xd5e6d4c9d7c7e2e3
637
	nwmTCPStatsIdentifier  = 0xd5e6d4e3c3d7e2e3
638
	nwmUDPStatsIdentifier  = 0xd5e6d4e4c4d7e2e3
639
	nwmICMPGStatsEntry     = 0xd5e6d4c9c3d4d7c7
640
	nwmICMPTStatsEntry     = 0xd5e6d4c9c3d4d7e3
641

642
	// nwmHeader constants
643
	nwmVersion1   = 1
644
	nwmVersion2   = 2
645
	nwmCurrentVer = 2
646

647
	nwmTCPConnType     = 1
648
	nwmGlobalStatsType = 14
649

650
	// nwmFilter constants
651
	nwmFilterLclAddrMask = 0x20000000 // Local address
652
	nwmFilterSrcAddrMask = 0x20000000 // Source address
653
	nwmFilterLclPortMask = 0x10000000 // Local port
654
	nwmFilterSrcPortMask = 0x10000000 // Source port
655

656
	// nwmConnEntry constants
657
	nwmTCPStateClosed   = 1
658
	nwmTCPStateListen   = 2
659
	nwmTCPStateSynSent  = 3
660
	nwmTCPStateSynRcvd  = 4
661
	nwmTCPStateEstab    = 5
662
	nwmTCPStateFinWait1 = 6
663
	nwmTCPStateFinWait2 = 7
664
	nwmTCPStateClosWait = 8
665
	nwmTCPStateLastAck  = 9
666
	nwmTCPStateClosing  = 10
667
	nwmTCPStateTimeWait = 11
668
	nwmTCPStateDeletTCB = 12
669

670
	// Existing constants on linux
671
	BPF_TCP_CLOSE        = 1
672
	BPF_TCP_LISTEN       = 2
673
	BPF_TCP_SYN_SENT     = 3
674
	BPF_TCP_SYN_RECV     = 4
675
	BPF_TCP_ESTABLISHED  = 5
676
	BPF_TCP_FIN_WAIT1    = 6
677
	BPF_TCP_FIN_WAIT2    = 7
678
	BPF_TCP_CLOSE_WAIT   = 8
679
	BPF_TCP_LAST_ACK     = 9
680
	BPF_TCP_CLOSING      = 10
681
	BPF_TCP_TIME_WAIT    = 11
682
	BPF_TCP_NEW_SYN_RECV = -1
683
	BPF_TCP_MAX_STATES   = -2
684
)
685

686
type nwmTriplet struct {
687
	offset uint32
688
	length uint32
689
	number uint32
690
}
691

692
type nwmQuadruplet struct {
693
	offset uint32
694
	length uint32
695
	number uint32
696
	match  uint32
697
}
698

699
type nwmHeader struct {
700
	ident       uint32
701
	length      uint32
702
	version     uint16
703
	nwmType     uint16
704
	bytesNeeded uint32
705
	options     uint32
706
	_           [16]byte
707
	inputDesc   nwmTriplet
708
	outputDesc  nwmQuadruplet
709
}
710

711
type nwmFilter struct {
712
	ident         uint32
713
	flags         uint32
714
	resourceName  [8]byte
715
	resourceId    uint32
716
	listenerId    uint32
717
	local         [28]byte // union of sockaddr4 and sockaddr6
718
	remote        [28]byte // union of sockaddr4 and sockaddr6
719
	_             uint16
720
	_             uint16
721
	asid          uint16
722
	_             [2]byte
723
	tnLuName      [8]byte
724
	tnMonGrp      uint32
725
	tnAppl        [8]byte
726
	applData      [40]byte
727
	nInterface    [16]byte
728
	dVipa         [16]byte
729
	dVipaPfx      uint16
730
	dVipaPort     uint16
731
	dVipaFamily   byte
732
	_             [3]byte
733
	destXCF       [16]byte
734
	destXCFPfx    uint16
735
	destXCFFamily byte
736
	_             [1]byte
737
	targIP        [16]byte
738
	targIPPfx     uint16
739
	targIPFamily  byte
740
	_             [1]byte
741
	_             [20]byte
742
}
743

744
type nwmRecHeader struct {
745
	ident  uint32
746
	length uint32
747
	number byte
748
	_      [3]byte
749
}
750

751
type nwmTCPStatsEntry struct {
752
	ident             uint64
753
	currEstab         uint32
754
	activeOpened      uint32
755
	passiveOpened     uint32
756
	connClosed        uint32
757
	estabResets       uint32
758
	attemptFails      uint32
759
	passiveDrops      uint32
760
	timeWaitReused    uint32
761
	inSegs            uint64
762
	predictAck        uint32
763
	predictData       uint32
764
	inDupAck          uint32
765
	inBadSum          uint32
766
	inBadLen          uint32
767
	inShort           uint32
768
	inDiscOldTime     uint32
769
	inAllBeforeWin    uint32
770
	inSomeBeforeWin   uint32
771
	inAllAfterWin     uint32
772
	inSomeAfterWin    uint32
773
	inOutOfOrder      uint32
774
	inAfterClose      uint32
775
	inWinProbes       uint32
776
	inWinUpdates      uint32
777
	outWinUpdates     uint32
778
	outSegs           uint64
779
	outDelayAcks      uint32
780
	outRsts           uint32
781
	retransSegs       uint32
782
	retransTimeouts   uint32
783
	retransDrops      uint32
784
	pmtuRetrans       uint32
785
	pmtuErrors        uint32
786
	outWinProbes      uint32
787
	probeDrops        uint32
788
	keepAliveProbes   uint32
789
	keepAliveDrops    uint32
790
	finwait2Drops     uint32
791
	acceptCount       uint64
792
	inBulkQSegs       uint64
793
	inDiscards        uint64
794
	connFloods        uint32
795
	connStalls        uint32
796
	cfgEphemDef       uint16
797
	ephemInUse        uint16
798
	ephemHiWater      uint16
799
	flags             byte
800
	_                 [1]byte
801
	ephemExhaust      uint32
802
	smcRCurrEstabLnks uint32
803
	smcRLnkActTimeOut uint32
804
	smcRActLnkOpened  uint32
805
	smcRPasLnkOpened  uint32
806
	smcRLnksClosed    uint32
807
	smcRCurrEstab     uint32
808
	smcRActiveOpened  uint32
809
	smcRPassiveOpened uint32
810
	smcRConnClosed    uint32
811
	smcRInSegs        uint64
812
	smcROutSegs       uint64
813
	smcRInRsts        uint32
814
	smcROutRsts       uint32
815
	smcDCurrEstabLnks uint32
816
	smcDActLnkOpened  uint32
817
	smcDPasLnkOpened  uint32
818
	smcDLnksClosed    uint32
819
	smcDCurrEstab     uint32
820
	smcDActiveOpened  uint32
821
	smcDPassiveOpened uint32
822
	smcDConnClosed    uint32
823
	smcDInSegs        uint64
824
	smcDOutSegs       uint64
825
	smcDInRsts        uint32
826
	smcDOutRsts       uint32
827
}
828

829
type nwmConnEntry struct {
830
	ident             uint32
831
	local             [28]byte // union of sockaddr4 and sockaddr6
832
	remote            [28]byte // union of sockaddr4 and sockaddr6
833
	startTime         [8]byte  // uint64, changed to prevent padding from being inserted
834
	lastActivity      [8]byte  // uint64
835
	bytesIn           [8]byte  // uint64
836
	bytesOut          [8]byte  // uint64
837
	inSegs            [8]byte  // uint64
838
	outSegs           [8]byte  // uint64
839
	state             uint16
840
	activeOpen        byte
841
	flag01            byte
842
	outBuffered       uint32
843
	inBuffered        uint32
844
	maxSndWnd         uint32
845
	reXmtCount        uint32
846
	congestionWnd     uint32
847
	ssThresh          uint32
848
	roundTripTime     uint32
849
	roundTripVar      uint32
850
	sendMSS           uint32
851
	sndWnd            uint32
852
	rcvBufSize        uint32
853
	sndBufSize        uint32
854
	outOfOrderCount   uint32
855
	lcl0WindowCount   uint32
856
	rmt0WindowCount   uint32
857
	dupacks           uint32
858
	flag02            byte
859
	sockOpt6Cont      byte
860
	asid              uint16
861
	resourceName      [8]byte
862
	resourceId        uint32
863
	subtask           uint32
864
	sockOpt           byte
865
	sockOpt6          byte
866
	clusterConnFlag   byte
867
	proto             byte
868
	targetAppl        [8]byte
869
	luName            [8]byte
870
	clientUserId      [8]byte
871
	logMode           [8]byte
872
	timeStamp         uint32
873
	timeStampAge      uint32
874
	serverResourceId  uint32
875
	intfName          [16]byte
876
	ttlsStatPol       byte
877
	ttlsStatConn      byte
878
	ttlsSSLProt       uint16
879
	ttlsNegCiph       [2]byte
880
	ttlsSecType       byte
881
	ttlsFIPS140Mode   byte
882
	ttlsUserID        [8]byte
883
	applData          [40]byte
884
	inOldestTime      [8]byte // uint64
885
	outOldestTime     [8]byte // uint64
886
	tcpTrustedPartner byte
887
	_                 [3]byte
888
	bulkDataIntfName  [16]byte
889
	ttlsNegCiph4      [4]byte
890
	smcReason         uint32
891
	lclSMCLinkId      uint32
892
	rmtSMCLinkId      uint32
893
	smcStatus         byte
894
	smcFlags          byte
895
	_                 [2]byte
896
	rcvWnd            uint32
897
	lclSMCBufSz       uint32
898
	rmtSMCBufSz       uint32
899
	ttlsSessID        [32]byte
900
	ttlsSessIDLen     int16
901
	_                 [1]byte
902
	smcDStatus        byte
903
	smcDReason        uint32
904
}
905

906
var svcNameTable [][]byte = [][]byte{
907
	[]byte("\xc5\xe9\xc2\xd5\xd4\xc9\xc6\xf4"), // svc_EZBNMIF4
908
}
909

910
const (
911
	svc_EZBNMIF4 = 0
912
)
913

914
func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) {
915
	jobname := []byte("\x5c\x40\x40\x40\x40\x40\x40\x40") // "*"
916
	responseBuffer := [4096]byte{0}
917
	var bufferAlet, reasonCode uint32 = 0, 0
918
	var bufferLen, returnValue, returnCode int32 = 4096, 0, 0
919

920
	dsa := [18]uint64{0}
921
	var argv [7]unsafe.Pointer
922
	argv[0] = unsafe.Pointer(&jobname[0])
923
	argv[1] = unsafe.Pointer(&responseBuffer[0])
924
	argv[2] = unsafe.Pointer(&bufferAlet)
925
	argv[3] = unsafe.Pointer(&bufferLen)
926
	argv[4] = unsafe.Pointer(&returnValue)
927
	argv[5] = unsafe.Pointer(&returnCode)
928
	argv[6] = unsafe.Pointer(&reasonCode)
929

930
	request := (*struct {
931
		header nwmHeader
932
		filter nwmFilter
933
	})(unsafe.Pointer(&responseBuffer[0]))
934

935
	EZBNMIF4 := svcLoad(&svcNameTable[svc_EZBNMIF4][0])
936
	if EZBNMIF4 == nil {
937
		return nil, errnoErr(EINVAL)
938
	}
939

940
	// GetGlobalStats EZBNMIF4 call
941
	request.header.ident = nwmHeaderIdentifier
942
	request.header.length = uint32(unsafe.Sizeof(request.header))
943
	request.header.version = nwmCurrentVer
944
	request.header.nwmType = nwmGlobalStatsType
945
	request.header.options = 0x80000000
946

947
	svcCall(EZBNMIF4, &argv[0], &dsa[0])
948

949
	// outputDesc field is filled by EZBNMIF4 on success
950
	if returnCode != 0 || request.header.outputDesc.offset == 0 {
951
		return nil, errnoErr(EINVAL)
952
	}
953

954
	// Check that EZBNMIF4 returned a nwmRecHeader
955
	recHeader := (*nwmRecHeader)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
956
	if recHeader.ident != nwmRecHeaderIdentifier {
957
		return nil, errnoErr(EINVAL)
958
	}
959

960
	// Parse nwmTriplets to get offsets of returned entries
961
	var sections []*uint64
962
	var sectionDesc *nwmTriplet = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[0]))
963
	for i := uint32(0); i < uint32(recHeader.number); i++ {
964
		offset := request.header.outputDesc.offset + uint32(unsafe.Sizeof(*recHeader)) + i*uint32(unsafe.Sizeof(*sectionDesc))
965
		sectionDesc = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[offset]))
966
		for j := uint32(0); j < sectionDesc.number; j++ {
967
			offset = request.header.outputDesc.offset + sectionDesc.offset + j*sectionDesc.length
968
			sections = append(sections, (*uint64)(unsafe.Pointer(&responseBuffer[offset])))
969
		}
970
	}
971

972
	// Find nwmTCPStatsEntry in returned entries
973
	var tcpStats *nwmTCPStatsEntry = nil
974
	for _, ptr := range sections {
975
		switch *ptr {
976
		case nwmTCPStatsIdentifier:
977
			if tcpStats != nil {
978
				return nil, errnoErr(EINVAL)
979
			}
980
			tcpStats = (*nwmTCPStatsEntry)(unsafe.Pointer(ptr))
981
		case nwmIPStatsIdentifier:
982
		case nwmIPGStatsIdentifier:
983
		case nwmUDPStatsIdentifier:
984
		case nwmICMPGStatsEntry:
985
		case nwmICMPTStatsEntry:
986
		default:
987
			return nil, errnoErr(EINVAL)
988
		}
989
	}
990
	if tcpStats == nil {
991
		return nil, errnoErr(EINVAL)
992
	}
993

994
	// GetConnectionDetail EZBNMIF4 call
995
	responseBuffer = [4096]byte{0}
996
	dsa = [18]uint64{0}
997
	bufferAlet, reasonCode = 0, 0
998
	bufferLen, returnValue, returnCode = 4096, 0, 0
999
	nameptr := (*uint32)(unsafe.Pointer(uintptr(0x21c))) // Get jobname of current process
1000
	nameptr = (*uint32)(unsafe.Pointer(uintptr(*nameptr + 12)))
1001
	argv[0] = unsafe.Pointer(uintptr(*nameptr))
1002

1003
	request.header.ident = nwmHeaderIdentifier
1004
	request.header.length = uint32(unsafe.Sizeof(request.header))
1005
	request.header.version = nwmCurrentVer
1006
	request.header.nwmType = nwmTCPConnType
1007
	request.header.options = 0x80000000
1008

1009
	request.filter.ident = nwmFilterIdentifier
1010

1011
	var localSockaddr RawSockaddrAny
1012
	socklen := _Socklen(SizeofSockaddrAny)
1013
	err := getsockname(fd, &localSockaddr, &socklen)
1014
	if err != nil {
1015
		return nil, errnoErr(EINVAL)
1016
	}
1017
	if localSockaddr.Addr.Family == AF_INET {
1018
		localSockaddr := (*RawSockaddrInet4)(unsafe.Pointer(&localSockaddr.Addr))
1019
		localSockFilter := (*RawSockaddrInet4)(unsafe.Pointer(&request.filter.local[0]))
1020
		localSockFilter.Family = AF_INET
1021
		var i int
1022
		for i = 0; i < 4; i++ {
1023
			if localSockaddr.Addr[i] != 0 {
1024
				break
1025
			}
1026
		}
1027
		if i != 4 {
1028
			request.filter.flags |= nwmFilterLclAddrMask
1029
			for i = 0; i < 4; i++ {
1030
				localSockFilter.Addr[i] = localSockaddr.Addr[i]
1031
			}
1032
		}
1033
		if localSockaddr.Port != 0 {
1034
			request.filter.flags |= nwmFilterLclPortMask
1035
			localSockFilter.Port = localSockaddr.Port
1036
		}
1037
	} else if localSockaddr.Addr.Family == AF_INET6 {
1038
		localSockaddr := (*RawSockaddrInet6)(unsafe.Pointer(&localSockaddr.Addr))
1039
		localSockFilter := (*RawSockaddrInet6)(unsafe.Pointer(&request.filter.local[0]))
1040
		localSockFilter.Family = AF_INET6
1041
		var i int
1042
		for i = 0; i < 16; i++ {
1043
			if localSockaddr.Addr[i] != 0 {
1044
				break
1045
			}
1046
		}
1047
		if i != 16 {
1048
			request.filter.flags |= nwmFilterLclAddrMask
1049
			for i = 0; i < 16; i++ {
1050
				localSockFilter.Addr[i] = localSockaddr.Addr[i]
1051
			}
1052
		}
1053
		if localSockaddr.Port != 0 {
1054
			request.filter.flags |= nwmFilterLclPortMask
1055
			localSockFilter.Port = localSockaddr.Port
1056
		}
1057
	}
1058

1059
	svcCall(EZBNMIF4, &argv[0], &dsa[0])
1060

1061
	// outputDesc field is filled by EZBNMIF4 on success
1062
	if returnCode != 0 || request.header.outputDesc.offset == 0 {
1063
		return nil, errnoErr(EINVAL)
1064
	}
1065

1066
	// Check that EZBNMIF4 returned a nwmConnEntry
1067
	conn := (*nwmConnEntry)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
1068
	if conn.ident != nwmTCPConnIdentifier {
1069
		return nil, errnoErr(EINVAL)
1070
	}
1071

1072
	// Copy data from the returned data structures into tcpInfo
1073
	// Stats from nwmConnEntry are specific to that connection.
1074
	// Stats from nwmTCPStatsEntry are global (to the interface?)
1075
	// Fields may not be an exact match. Some fields have no equivalent.
1076
	var tcpinfo TCPInfo
1077
	tcpinfo.State = uint8(conn.state)
1078
	tcpinfo.Ca_state = 0 // dummy
1079
	tcpinfo.Retransmits = uint8(tcpStats.retransSegs)
1080
	tcpinfo.Probes = uint8(tcpStats.outWinProbes)
1081
	tcpinfo.Backoff = 0 // dummy
1082
	tcpinfo.Options = 0 // dummy
1083
	tcpinfo.Rto = tcpStats.retransTimeouts
1084
	tcpinfo.Ato = tcpStats.outDelayAcks
1085
	tcpinfo.Snd_mss = conn.sendMSS
1086
	tcpinfo.Rcv_mss = conn.sendMSS // dummy
1087
	tcpinfo.Unacked = 0            // dummy
1088
	tcpinfo.Sacked = 0             // dummy
1089
	tcpinfo.Lost = 0               // dummy
1090
	tcpinfo.Retrans = conn.reXmtCount
1091
	tcpinfo.Fackets = 0 // dummy
1092
	tcpinfo.Last_data_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.lastActivity[0])))
1093
	tcpinfo.Last_ack_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.outOldestTime[0])))
1094
	tcpinfo.Last_data_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
1095
	tcpinfo.Last_ack_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
1096
	tcpinfo.Pmtu = conn.sendMSS // dummy, NWMIfRouteMtu is a candidate
1097
	tcpinfo.Rcv_ssthresh = conn.ssThresh
1098
	tcpinfo.Rtt = conn.roundTripTime
1099
	tcpinfo.Rttvar = conn.roundTripVar
1100
	tcpinfo.Snd_ssthresh = conn.ssThresh // dummy
1101
	tcpinfo.Snd_cwnd = conn.congestionWnd
1102
	tcpinfo.Advmss = conn.sendMSS        // dummy
1103
	tcpinfo.Reordering = 0               // dummy
1104
	tcpinfo.Rcv_rtt = conn.roundTripTime // dummy
1105
	tcpinfo.Rcv_space = conn.sendMSS     // dummy
1106
	tcpinfo.Total_retrans = conn.reXmtCount
1107

1108
	svcUnload(&svcNameTable[svc_EZBNMIF4][0], EZBNMIF4)
1109

1110
	return &tcpinfo, nil
1111
}
1112

1113
// GetsockoptString returns the string value of the socket option opt for the
1114
// socket associated with fd at the given socket level.
1115
func GetsockoptString(fd, level, opt int) (string, error) {
1116
	buf := make([]byte, 256)
1117
	vallen := _Socklen(len(buf))
1118
	err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
1119
	if err != nil {
1120
		return "", err
1121
	}
1122

1123
	return string(buf[:vallen-1]), nil
1124
}
1125

1126
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
1127
	var msg Msghdr
1128
	var rsa RawSockaddrAny
1129
	msg.Name = (*byte)(unsafe.Pointer(&rsa))
1130
	msg.Namelen = SizeofSockaddrAny
1131
	var iov Iovec
1132
	if len(p) > 0 {
1133
		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
1134
		iov.SetLen(len(p))
1135
	}
1136
	var dummy byte
1137
	if len(oob) > 0 {
1138
		// receive at least one normal byte
1139
		if len(p) == 0 {
1140
			iov.Base = &dummy
1141
			iov.SetLen(1)
1142
		}
1143
		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
1144
		msg.SetControllen(len(oob))
1145
	}
1146
	msg.Iov = &iov
1147
	msg.Iovlen = 1
1148
	if n, err = recvmsg(fd, &msg, flags); err != nil {
1149
		return
1150
	}
1151
	oobn = int(msg.Controllen)
1152
	recvflags = int(msg.Flags)
1153
	// source address is only specified if the socket is unconnected
1154
	if rsa.Addr.Family != AF_UNSPEC {
1155
		// TODO(neeilan): Remove 0 arg added to get this compiling on z/OS
1156
		from, err = anyToSockaddr(0, &rsa)
1157
	}
1158
	return
1159
}
1160

1161
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
1162
	_, err = SendmsgN(fd, p, oob, to, flags)
1163
	return
1164
}
1165

1166
func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
1167
	var ptr unsafe.Pointer
1168
	var salen _Socklen
1169
	if to != nil {
1170
		var err error
1171
		ptr, salen, err = to.sockaddr()
1172
		if err != nil {
1173
			return 0, err
1174
		}
1175
	}
1176
	var msg Msghdr
1177
	msg.Name = (*byte)(unsafe.Pointer(ptr))
1178
	msg.Namelen = int32(salen)
1179
	var iov Iovec
1180
	if len(p) > 0 {
1181
		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
1182
		iov.SetLen(len(p))
1183
	}
1184
	var dummy byte
1185
	if len(oob) > 0 {
1186
		// send at least one normal byte
1187
		if len(p) == 0 {
1188
			iov.Base = &dummy
1189
			iov.SetLen(1)
1190
		}
1191
		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
1192
		msg.SetControllen(len(oob))
1193
	}
1194
	msg.Iov = &iov
1195
	msg.Iovlen = 1
1196
	if n, err = sendmsg(fd, &msg, flags); err != nil {
1197
		return 0, err
1198
	}
1199
	if len(oob) > 0 && len(p) == 0 {
1200
		n = 0
1201
	}
1202
	return n, nil
1203
}
1204

1205
func Opendir(name string) (uintptr, error) {
1206
	p, err := BytePtrFromString(name)
1207
	if err != nil {
1208
		return 0, err
1209
	}
1210
	dir, _, e := syscall_syscall(SYS___OPENDIR_A, uintptr(unsafe.Pointer(p)), 0, 0)
1211
	runtime.KeepAlive(unsafe.Pointer(p))
1212
	if e != 0 {
1213
		err = errnoErr(e)
1214
	}
1215
	return dir, err
1216
}
1217

1218
// clearsyscall.Errno resets the errno value to 0.
1219
func clearErrno()
1220

1221
func Readdir(dir uintptr) (*Dirent, error) {
1222
	var ent Dirent
1223
	var res uintptr
1224
	// __readdir_r_a returns errno at the end of the directory stream, rather than 0.
1225
	// Therefore to avoid false positives we clear errno before calling it.
1226

1227
	// TODO(neeilan): Commented this out to get sys/unix compiling on z/OS. Uncomment and fix. Error: "undefined: clearsyscall"
1228
	//clearsyscall.Errno() // TODO(mundaym): check pre-emption rules.
1229

1230
	e, _, _ := syscall_syscall(SYS___READDIR_R_A, dir, uintptr(unsafe.Pointer(&ent)), uintptr(unsafe.Pointer(&res)))
1231
	var err error
1232
	if e != 0 {
1233
		err = errnoErr(Errno(e))
1234
	}
1235
	if res == 0 {
1236
		return nil, err
1237
	}
1238
	return &ent, err
1239
}
1240

1241
func readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) {
1242
	r0, _, e1 := syscall_syscall(SYS___READDIR_R_A, dirp, uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result)))
1243
	if int64(r0) == -1 {
1244
		err = errnoErr(Errno(e1))
1245
	}
1246
	return
1247
}
1248

1249
func Closedir(dir uintptr) error {
1250
	_, _, e := syscall_syscall(SYS_CLOSEDIR, dir, 0, 0)
1251
	if e != 0 {
1252
		return errnoErr(e)
1253
	}
1254
	return nil
1255
}
1256

1257
func Seekdir(dir uintptr, pos int) {
1258
	_, _, _ = syscall_syscall(SYS_SEEKDIR, dir, uintptr(pos), 0)
1259
}
1260

1261
func Telldir(dir uintptr) (int, error) {
1262
	p, _, e := syscall_syscall(SYS_TELLDIR, dir, 0, 0)
1263
	pos := int(p)
1264
	if pos == -1 {
1265
		return pos, errnoErr(e)
1266
	}
1267
	return pos, nil
1268
}
1269

1270
// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
1271
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
1272
	// struct flock is packed on z/OS. We can't emulate that in Go so
1273
	// instead we pack it here.
1274
	var flock [24]byte
1275
	*(*int16)(unsafe.Pointer(&flock[0])) = lk.Type
1276
	*(*int16)(unsafe.Pointer(&flock[2])) = lk.Whence
1277
	*(*int64)(unsafe.Pointer(&flock[4])) = lk.Start
1278
	*(*int64)(unsafe.Pointer(&flock[12])) = lk.Len
1279
	*(*int32)(unsafe.Pointer(&flock[20])) = lk.Pid
1280
	_, _, errno := syscall_syscall(SYS_FCNTL, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock)))
1281
	lk.Type = *(*int16)(unsafe.Pointer(&flock[0]))
1282
	lk.Whence = *(*int16)(unsafe.Pointer(&flock[2]))
1283
	lk.Start = *(*int64)(unsafe.Pointer(&flock[4]))
1284
	lk.Len = *(*int64)(unsafe.Pointer(&flock[12]))
1285
	lk.Pid = *(*int32)(unsafe.Pointer(&flock[20]))
1286
	if errno == 0 {
1287
		return nil
1288
	}
1289
	return errno
1290
}
1291

1292
func Flock(fd int, how int) error {
1293

1294
	var flock_type int16
1295
	var fcntl_cmd int
1296

1297
	switch how {
1298
	case LOCK_SH | LOCK_NB:
1299
		flock_type = F_RDLCK
1300
		fcntl_cmd = F_SETLK
1301
	case LOCK_EX | LOCK_NB:
1302
		flock_type = F_WRLCK
1303
		fcntl_cmd = F_SETLK
1304
	case LOCK_EX:
1305
		flock_type = F_WRLCK
1306
		fcntl_cmd = F_SETLKW
1307
	case LOCK_UN:
1308
		flock_type = F_UNLCK
1309
		fcntl_cmd = F_SETLKW
1310
	default:
1311
	}
1312

1313
	flock := Flock_t{
1314
		Type:   int16(flock_type),
1315
		Whence: int16(0),
1316
		Start:  int64(0),
1317
		Len:    int64(0),
1318
		Pid:    int32(Getppid()),
1319
	}
1320

1321
	err := FcntlFlock(uintptr(fd), fcntl_cmd, &flock)
1322
	return err
1323
}
1324

1325
func Mlock(b []byte) (err error) {
1326
	_, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
1327
	if e1 != 0 {
1328
		err = errnoErr(e1)
1329
	}
1330
	return
1331
}
1332

1333
func Mlock2(b []byte, flags int) (err error) {
1334
	_, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
1335
	if e1 != 0 {
1336
		err = errnoErr(e1)
1337
	}
1338
	return
1339
}
1340

1341
func Mlockall(flags int) (err error) {
1342
	_, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
1343
	if e1 != 0 {
1344
		err = errnoErr(e1)
1345
	}
1346
	return
1347
}
1348

1349
func Munlock(b []byte) (err error) {
1350
	_, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0)
1351
	if e1 != 0 {
1352
		err = errnoErr(e1)
1353
	}
1354
	return
1355
}
1356

1357
func Munlockall() (err error) {
1358
	_, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0)
1359
	if e1 != 0 {
1360
		err = errnoErr(e1)
1361
	}
1362
	return
1363
}
1364

1365
func ClockGettime(clockid int32, ts *Timespec) error {
1366

1367
	var ticks_per_sec uint32 = 100 //TODO(kenan): value is currently hardcoded; need sysconf() call otherwise
1368
	var nsec_per_sec int64 = 1000000000
1369

1370
	if ts == nil {
1371
		return EFAULT
1372
	}
1373
	if clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC {
1374
		var nanotime int64 = runtime.Nanotime1()
1375
		ts.Sec = nanotime / nsec_per_sec
1376
		ts.Nsec = nanotime % nsec_per_sec
1377
	} else if clockid == CLOCK_PROCESS_CPUTIME_ID || clockid == CLOCK_THREAD_CPUTIME_ID {
1378
		var tm Tms
1379
		_, err := Times(&tm)
1380
		if err != nil {
1381
			return EFAULT
1382
		}
1383
		ts.Sec = int64(tm.Utime / ticks_per_sec)
1384
		ts.Nsec = int64(tm.Utime) * nsec_per_sec / int64(ticks_per_sec)
1385
	} else {
1386
		return EINVAL
1387
	}
1388
	return nil
1389
}
1390

1391
func Statfs(path string, stat *Statfs_t) (err error) {
1392
	fd, err := open(path, O_RDONLY, 0)
1393
	defer Close(fd)
1394
	if err != nil {
1395
		return err
1396
	}
1397
	return Fstatfs(fd, stat)
1398
}
1399

1400
var (
1401
	Stdin  = 0
1402
	Stdout = 1
1403
	Stderr = 2
1404
)
1405

1406
// Do the interface allocations only once for common
1407
// Errno values.
1408
var (
1409
	errEAGAIN error = syscall.EAGAIN
1410
	errEINVAL error = syscall.EINVAL
1411
	errENOENT error = syscall.ENOENT
1412
)
1413

1414
var (
1415
	signalNameMapOnce sync.Once
1416
	signalNameMap     map[string]syscall.Signal
1417
)
1418

1419
// errnoErr returns common boxed Errno values, to prevent
1420
// allocations at runtime.
1421
func errnoErr(e Errno) error {
1422
	switch e {
1423
	case 0:
1424
		return nil
1425
	case EAGAIN:
1426
		return errEAGAIN
1427
	case EINVAL:
1428
		return errEINVAL
1429
	case ENOENT:
1430
		return errENOENT
1431
	}
1432
	return e
1433
}
1434

1435
// ErrnoName returns the error name for error number e.
1436
func ErrnoName(e Errno) string {
1437
	i := sort.Search(len(errorList), func(i int) bool {
1438
		return errorList[i].num >= e
1439
	})
1440
	if i < len(errorList) && errorList[i].num == e {
1441
		return errorList[i].name
1442
	}
1443
	return ""
1444
}
1445

1446
// SignalName returns the signal name for signal number s.
1447
func SignalName(s syscall.Signal) string {
1448
	i := sort.Search(len(signalList), func(i int) bool {
1449
		return signalList[i].num >= s
1450
	})
1451
	if i < len(signalList) && signalList[i].num == s {
1452
		return signalList[i].name
1453
	}
1454
	return ""
1455
}
1456

1457
// SignalNum returns the syscall.Signal for signal named s,
1458
// or 0 if a signal with such name is not found.
1459
// The signal name should start with "SIG".
1460
func SignalNum(s string) syscall.Signal {
1461
	signalNameMapOnce.Do(func() {
1462
		signalNameMap = make(map[string]syscall.Signal, len(signalList))
1463
		for _, signal := range signalList {
1464
			signalNameMap[signal.name] = signal.num
1465
		}
1466
	})
1467
	return signalNameMap[s]
1468
}
1469

1470
// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
1471
func clen(n []byte) int {
1472
	i := bytes.IndexByte(n, 0)
1473
	if i == -1 {
1474
		i = len(n)
1475
	}
1476
	return i
1477
}
1478

1479
// Mmap manager, for use by operating system-specific implementations.
1480

1481
type mmapper struct {
1482
	sync.Mutex
1483
	active map[*byte][]byte // active mappings; key is last byte in mapping
1484
	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
1485
	munmap func(addr uintptr, length uintptr) error
1486
}
1487

1488
func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
1489
	if length <= 0 {
1490
		return nil, EINVAL
1491
	}
1492

1493
	// Map the requested memory.
1494
	addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
1495
	if errno != nil {
1496
		return nil, errno
1497
	}
1498

1499
	// Slice memory layout
1500
	var sl = struct {
1501
		addr uintptr
1502
		len  int
1503
		cap  int
1504
	}{addr, length, length}
1505

1506
	// Use unsafe to turn sl into a []byte.
1507
	b := *(*[]byte)(unsafe.Pointer(&sl))
1508

1509
	// Register mapping in m and return it.
1510
	p := &b[cap(b)-1]
1511
	m.Lock()
1512
	defer m.Unlock()
1513
	m.active[p] = b
1514
	return b, nil
1515
}
1516

1517
func (m *mmapper) Munmap(data []byte) (err error) {
1518
	if len(data) == 0 || len(data) != cap(data) {
1519
		return EINVAL
1520
	}
1521

1522
	// Find the base of the mapping.
1523
	p := &data[cap(data)-1]
1524
	m.Lock()
1525
	defer m.Unlock()
1526
	b := m.active[p]
1527
	if b == nil || &b[0] != &data[0] {
1528
		return EINVAL
1529
	}
1530

1531
	// Unmap the memory and update m.
1532
	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
1533
		return errno
1534
	}
1535
	delete(m.active, p)
1536
	return nil
1537
}
1538

1539
func Read(fd int, p []byte) (n int, err error) {
1540
	n, err = read(fd, p)
1541
	if raceenabled {
1542
		if n > 0 {
1543
			raceWriteRange(unsafe.Pointer(&p[0]), n)
1544
		}
1545
		if err == nil {
1546
			raceAcquire(unsafe.Pointer(&ioSync))
1547
		}
1548
	}
1549
	return
1550
}
1551

1552
func Write(fd int, p []byte) (n int, err error) {
1553
	if raceenabled {
1554
		raceReleaseMerge(unsafe.Pointer(&ioSync))
1555
	}
1556
	n, err = write(fd, p)
1557
	if raceenabled && n > 0 {
1558
		raceReadRange(unsafe.Pointer(&p[0]), n)
1559
	}
1560
	return
1561
}
1562

1563
// For testing: clients can set this flag to force
1564
// creation of IPv6 sockets to return EAFNOSUPPORT.
1565
var SocketDisableIPv6 bool
1566

1567
// Sockaddr represents a socket address.
1568
type Sockaddr interface {
1569
	sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs
1570
}
1571

1572
// SockaddrInet4 implements the Sockaddr interface for AF_INET type sockets.
1573
type SockaddrInet4 struct {
1574
	Port int
1575
	Addr [4]byte
1576
	raw  RawSockaddrInet4
1577
}
1578

1579
// SockaddrInet6 implements the Sockaddr interface for AF_INET6 type sockets.
1580
type SockaddrInet6 struct {
1581
	Port   int
1582
	ZoneId uint32
1583
	Addr   [16]byte
1584
	raw    RawSockaddrInet6
1585
}
1586

1587
// SockaddrUnix implements the Sockaddr interface for AF_UNIX type sockets.
1588
type SockaddrUnix struct {
1589
	Name string
1590
	raw  RawSockaddrUnix
1591
}
1592

1593
func Bind(fd int, sa Sockaddr) (err error) {
1594
	ptr, n, err := sa.sockaddr()
1595
	if err != nil {
1596
		return err
1597
	}
1598
	return bind(fd, ptr, n)
1599
}
1600

1601
func Connect(fd int, sa Sockaddr) (err error) {
1602
	ptr, n, err := sa.sockaddr()
1603
	if err != nil {
1604
		return err
1605
	}
1606
	return connect(fd, ptr, n)
1607
}
1608

1609
func Getpeername(fd int) (sa Sockaddr, err error) {
1610
	var rsa RawSockaddrAny
1611
	var len _Socklen = SizeofSockaddrAny
1612
	if err = getpeername(fd, &rsa, &len); err != nil {
1613
		return
1614
	}
1615
	return anyToSockaddr(fd, &rsa)
1616
}
1617

1618
func GetsockoptByte(fd, level, opt int) (value byte, err error) {
1619
	var n byte
1620
	vallen := _Socklen(1)
1621
	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
1622
	return n, err
1623
}
1624

1625
func GetsockoptInt(fd, level, opt int) (value int, err error) {
1626
	var n int32
1627
	vallen := _Socklen(4)
1628
	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
1629
	return int(n), err
1630
}
1631

1632
func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
1633
	vallen := _Socklen(4)
1634
	err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
1635
	return value, err
1636
}
1637

1638
func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
1639
	var value IPMreq
1640
	vallen := _Socklen(SizeofIPMreq)
1641
	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
1642
	return &value, err
1643
}
1644

1645
func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
1646
	var value IPv6Mreq
1647
	vallen := _Socklen(SizeofIPv6Mreq)
1648
	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
1649
	return &value, err
1650
}
1651

1652
func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) {
1653
	var value IPv6MTUInfo
1654
	vallen := _Socklen(SizeofIPv6MTUInfo)
1655
	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
1656
	return &value, err
1657
}
1658

1659
func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {
1660
	var value ICMPv6Filter
1661
	vallen := _Socklen(SizeofICMPv6Filter)
1662
	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
1663
	return &value, err
1664
}
1665

1666
func GetsockoptLinger(fd, level, opt int) (*Linger, error) {
1667
	var linger Linger
1668
	vallen := _Socklen(SizeofLinger)
1669
	err := getsockopt(fd, level, opt, unsafe.Pointer(&linger), &vallen)
1670
	return &linger, err
1671
}
1672

1673
func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) {
1674
	var tv Timeval
1675
	vallen := _Socklen(unsafe.Sizeof(tv))
1676
	err := getsockopt(fd, level, opt, unsafe.Pointer(&tv), &vallen)
1677
	return &tv, err
1678
}
1679

1680
func GetsockoptUint64(fd, level, opt int) (value uint64, err error) {
1681
	var n uint64
1682
	vallen := _Socklen(8)
1683
	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
1684
	return n, err
1685
}
1686

1687
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
1688
	var rsa RawSockaddrAny
1689
	var len _Socklen = SizeofSockaddrAny
1690
	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
1691
		return
1692
	}
1693
	if rsa.Addr.Family != AF_UNSPEC {
1694
		from, err = anyToSockaddr(fd, &rsa)
1695
	}
1696
	return
1697
}
1698

1699
func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
1700
	ptr, n, err := to.sockaddr()
1701
	if err != nil {
1702
		return err
1703
	}
1704
	return sendto(fd, p, flags, ptr, n)
1705
}
1706

1707
func SetsockoptByte(fd, level, opt int, value byte) (err error) {
1708
	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
1709
}
1710

1711
func SetsockoptInt(fd, level, opt int, value int) (err error) {
1712
	var n = int32(value)
1713
	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
1714
}
1715

1716
func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
1717
	return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
1718
}
1719

1720
func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
1721
	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq)
1722
}
1723

1724
func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
1725
	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq)
1726
}
1727

1728
func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
1729
	return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
1730
}
1731

1732
func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
1733
	return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger)
1734
}
1735

1736
func SetsockoptString(fd, level, opt int, s string) (err error) {
1737
	var p unsafe.Pointer
1738
	if len(s) > 0 {
1739
		p = unsafe.Pointer(&[]byte(s)[0])
1740
	}
1741
	return setsockopt(fd, level, opt, p, uintptr(len(s)))
1742
}
1743

1744
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
1745
	return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv))
1746
}
1747

1748
func SetsockoptUint64(fd, level, opt int, value uint64) (err error) {
1749
	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 8)
1750
}
1751

1752
func Socket(domain, typ, proto int) (fd int, err error) {
1753
	if domain == AF_INET6 && SocketDisableIPv6 {
1754
		return -1, EAFNOSUPPORT
1755
	}
1756
	fd, err = socket(domain, typ, proto)
1757
	return
1758
}
1759

1760
func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
1761
	var fdx [2]int32
1762
	err = socketpair(domain, typ, proto, &fdx)
1763
	if err == nil {
1764
		fd[0] = int(fdx[0])
1765
		fd[1] = int(fdx[1])
1766
	}
1767
	return
1768
}
1769

1770
var ioSync int64
1771

1772
func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
1773

1774
func SetNonblock(fd int, nonblocking bool) (err error) {
1775
	flag, err := fcntl(fd, F_GETFL, 0)
1776
	if err != nil {
1777
		return err
1778
	}
1779
	if nonblocking {
1780
		flag |= O_NONBLOCK
1781
	} else {
1782
		flag &= ^O_NONBLOCK
1783
	}
1784
	_, err = fcntl(fd, F_SETFL, flag)
1785
	return err
1786
}
1787

1788
// Exec calls execve(2), which replaces the calling executable in the process
1789
// tree. argv0 should be the full path to an executable ("/bin/ls") and the
1790
// executable name should also be the first argument in argv (["ls", "-l"]).
1791
// envv are the environment variables that should be passed to the new
1792
// process (["USER=go", "PWD=/tmp"]).
1793
func Exec(argv0 string, argv []string, envv []string) error {
1794
	return syscall.Exec(argv0, argv, envv)
1795
}
1796

1797
func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
1798
	if needspace := 8 - len(fstype); needspace <= 0 {
1799
		fstype = fstype[:8]
1800
	} else {
1801
		fstype += "        "[:needspace]
1802
	}
1803
	return mount_LE(target, source, fstype, uint32(flags), int32(len(data)), data)
1804
}
1805

1806
func Unmount(name string, mtm int) (err error) {
1807
	// mountpoint is always a full path and starts with a '/'
1808
	// check if input string is not a mountpoint but a filesystem name
1809
	if name[0] != '/' {
1810
		return unmount(name, mtm)
1811
	}
1812
	// treat name as mountpoint
1813
	b2s := func(arr []byte) string {
1814
		nulli := bytes.IndexByte(arr, 0)
1815
		if nulli == -1 {
1816
			return string(arr)
1817
		} else {
1818
			return string(arr[:nulli])
1819
		}
1820
	}
1821
	var buffer struct {
1822
		header W_Mnth
1823
		fsinfo [64]W_Mntent
1824
	}
1825
	fsCount, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer)))
1826
	if err != nil {
1827
		return err
1828
	}
1829
	if fsCount == 0 {
1830
		return EINVAL
1831
	}
1832
	for i := 0; i < fsCount; i++ {
1833
		if b2s(buffer.fsinfo[i].Mountpoint[:]) == name {
1834
			err = unmount(b2s(buffer.fsinfo[i].Fsname[:]), mtm)
1835
			break
1836
		}
1837
	}
1838
	return err
1839
}
1840

1841
func fdToPath(dirfd int) (path string, err error) {
1842
	var buffer [1024]byte
1843
	// w_ctrl()
1844
	ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4,
1845
		[]uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))})
1846
	if ret == 0 {
1847
		zb := bytes.IndexByte(buffer[:], 0)
1848
		if zb == -1 {
1849
			zb = len(buffer)
1850
		}
1851
		// __e2a_l()
1852
		runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4,
1853
			[]uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)})
1854
		return string(buffer[:zb]), nil
1855
	}
1856
	// __errno()
1857
	errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4,
1858
		[]uintptr{}))))
1859
	// __errno2()
1860
	errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4,
1861
		[]uintptr{}))
1862
	// strerror_r()
1863
	ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4,
1864
		[]uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024})
1865
	if ret == 0 {
1866
		zb := bytes.IndexByte(buffer[:], 0)
1867
		if zb == -1 {
1868
			zb = len(buffer)
1869
		}
1870
		return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2)
1871
	} else {
1872
		return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2)
1873
	}
1874
}
1875

1876
func direntLeToDirentUnix(dirent *direntLE, dir uintptr, path string) (Dirent, error) {
1877
	var d Dirent
1878

1879
	d.Ino = uint64(dirent.Ino)
1880
	offset, err := Telldir(dir)
1881
	if err != nil {
1882
		return d, err
1883
	}
1884

1885
	d.Off = int64(offset)
1886
	s := string(bytes.Split(dirent.Name[:], []byte{0})[0])
1887
	copy(d.Name[:], s)
1888

1889
	d.Reclen = uint16(24 + len(d.NameString()))
1890
	var st Stat_t
1891
	path = path + "/" + s
1892
	err = Lstat(path, &st)
1893
	if err != nil {
1894
		return d, err
1895
	}
1896

1897
	d.Type = uint8(st.Mode >> 24)
1898
	return d, err
1899
}
1900

1901
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
1902
	// Simulation of Getdirentries port from the Darwin implementation.
1903
	// COMMENTS FROM DARWIN:
1904
	// It's not the full required semantics, but should handle the case
1905
	// of calling Getdirentries or ReadDirent repeatedly.
1906
	// It won't handle assigning the results of lseek to *basep, or handle
1907
	// the directory being edited underfoot.
1908

1909
	skip, err := Seek(fd, 0, 1 /* SEEK_CUR */)
1910
	if err != nil {
1911
		return 0, err
1912
	}
1913

1914
	// Get path from fd to avoid unavailable call (fdopendir)
1915
	path, err := fdToPath(fd)
1916
	if err != nil {
1917
		return 0, err
1918
	}
1919
	d, err := Opendir(path)
1920
	if err != nil {
1921
		return 0, err
1922
	}
1923
	defer Closedir(d)
1924

1925
	var cnt int64
1926
	for {
1927
		var entryLE direntLE
1928
		var entrypLE *direntLE
1929
		e := readdir_r(d, &entryLE, &entrypLE)
1930
		if e != nil {
1931
			return n, e
1932
		}
1933
		if entrypLE == nil {
1934
			break
1935
		}
1936
		if skip > 0 {
1937
			skip--
1938
			cnt++
1939
			continue
1940
		}
1941

1942
		// Dirent on zos has a different structure
1943
		entry, e := direntLeToDirentUnix(&entryLE, d, path)
1944
		if e != nil {
1945
			return n, e
1946
		}
1947

1948
		reclen := int(entry.Reclen)
1949
		if reclen > len(buf) {
1950
			// Not enough room. Return for now.
1951
			// The counter will let us know where we should start up again.
1952
			// Note: this strategy for suspending in the middle and
1953
			// restarting is O(n^2) in the length of the directory. Oh well.
1954
			break
1955
		}
1956

1957
		// Copy entry into return buffer.
1958
		s := unsafe.Slice((*byte)(unsafe.Pointer(&entry)), reclen)
1959
		copy(buf, s)
1960

1961
		buf = buf[reclen:]
1962
		n += reclen
1963
		cnt++
1964
	}
1965
	// Set the seek offset of the input fd to record
1966
	// how many files we've already returned.
1967
	_, err = Seek(fd, cnt, 0 /* SEEK_SET */)
1968
	if err != nil {
1969
		return n, err
1970
	}
1971

1972
	return n, nil
1973
}
1974

1975
func ReadDirent(fd int, buf []byte) (n int, err error) {
1976
	var base = (*uintptr)(unsafe.Pointer(new(uint64)))
1977
	return Getdirentries(fd, buf, base)
1978
}
1979

1980
func direntIno(buf []byte) (uint64, bool) {
1981
	return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
1982
}
1983

1984
func direntReclen(buf []byte) (uint64, bool) {
1985
	return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
1986
}
1987

1988
func direntNamlen(buf []byte) (uint64, bool) {
1989
	reclen, ok := direntReclen(buf)
1990
	if !ok {
1991
		return 0, false
1992
	}
1993
	return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
1994
}
1995

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.