1// Copyright 2018 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// Aix system calls.
6// This file is compiled as ordinary Go code,
7// but it is also input to mksyscall,
8// which parses the //sys lines and generates system call stubs.
9// Note that sometimes we use a lowercase //sys name and
10// wrap it in our own nicer implementation.
11
12package syscall
13
14import (
15	"unsafe"
16)
17
18func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
19func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
20func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
21func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
22
23// Implemented in runtime/syscall_aix.go.
24func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
25func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
26
27// Constant expected by package but not supported
28const (
29	_ = iota
30	TIOCSCTTY
31	SYS_EXECVE
32	SYS_FCNTL
33)
34
35const (
36	F_DUPFD_CLOEXEC = 0
37	// AF_LOCAL doesn't exist on AIX
38	AF_LOCAL = AF_UNIX
39
40	_F_DUP2FD_CLOEXEC = 0
41)
42
43func (ts *StTimespec_t) Unix() (sec int64, nsec int64) {
44	return int64(ts.Sec), int64(ts.Nsec)
45}
46
47func (ts *StTimespec_t) Nano() int64 {
48	return int64(ts.Sec)*1e9 + int64(ts.Nsec)
49}
50
51/*
52 * Wrapped
53 */
54
55func Access(path string, mode uint32) (err error) {
56	return Faccessat(_AT_FDCWD, path, mode, 0)
57}
58
59// fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX
60// There is no way to create a custom fcntl and to keep //sys fcntl easily,
61// because we need fcntl name for its libc symbol. This is linked with the script.
62// But, as fcntl is currently not exported and isn't called with F_DUP2FD,
63// it doesn't matter.
64//sys	fcntl(fd int, cmd int, arg int) (val int, err error)
65//sys	Dup2(old int, new int) (err error)
66
67//sysnb pipe(p *[2]_C_int) (err error)
68
69func Pipe(p []int) (err error) {
70	if len(p) != 2 {
71		return EINVAL
72	}
73	var pp [2]_C_int
74	err = pipe(&pp)
75	if err == nil {
76		p[0] = int(pp[0])
77		p[1] = int(pp[1])
78	}
79	return
80}
81
82//sys	readlink(path string, buf []byte, bufSize uint64) (n int, err error)
83
84func Readlink(path string, buf []byte) (n int, err error) {
85	s := uint64(len(buf))
86	return readlink(path, buf, s)
87}
88
89//sys	utimes(path string, times *[2]Timeval) (err error)
90
91func Utimes(path string, tv []Timeval) error {
92	if len(tv) != 2 {
93		return EINVAL
94	}
95	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
96}
97
98//sys	utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error)
99
100func UtimesNano(path string, ts []Timespec) error {
101	if len(ts) != 2 {
102		return EINVAL
103	}
104	return utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
105}
106
107//sys	unlinkat(dirfd int, path string, flags int) (err error)
108
109func Unlinkat(dirfd int, path string) (err error) {
110	return unlinkat(dirfd, path, 0)
111}
112
113//sys	getcwd(buf *byte, size uint64) (err error)
114
115const ImplementsGetwd = true
116
117func Getwd() (ret string, err error) {
118	for len := uint64(4096); ; len *= 2 {
119		b := make([]byte, len)
120		err := getcwd(&b[0], len)
121		if err == nil {
122			i := 0
123			for b[i] != 0 {
124				i++
125			}
126			return string(b[0:i]), nil
127		}
128		if err != ERANGE {
129			return "", err
130		}
131	}
132}
133
134func Getcwd(buf []byte) (n int, err error) {
135	err = getcwd(&buf[0], uint64(len(buf)))
136	if err == nil {
137		i := 0
138		for buf[i] != 0 {
139			i++
140		}
141		n = i + 1
142	}
143	return
144}
145
146//sysnb	getgroups(ngid int, gid *_Gid_t) (n int, err error)
147//sysnb	setgroups(ngid int, gid *_Gid_t) (err error)
148
149func Getgroups() (gids []int, err error) {
150	n, err := getgroups(0, nil)
151	if err != nil {
152		return nil, err
153	}
154	if n == 0 {
155		return nil, nil
156	}
157
158	// Sanity check group count. Max is 16 on BSD.
159	if n < 0 || n > 1000 {
160		return nil, EINVAL
161	}
162
163	a := make([]_Gid_t, n)
164	n, err = getgroups(n, &a[0])
165	if err != nil {
166		return nil, err
167	}
168	gids = make([]int, n)
169	for i, v := range a[0:n] {
170		gids[i] = int(v)
171	}
172	return
173}
174
175func Setgroups(gids []int) (err error) {
176	if len(gids) == 0 {
177		return setgroups(0, nil)
178	}
179
180	a := make([]_Gid_t, len(gids))
181	for i, v := range gids {
182		a[i] = _Gid_t(v)
183	}
184	return setgroups(len(a), &a[0])
185}
186
187func direntIno(buf []byte) (uint64, bool) {
188	return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
189}
190
191func direntReclen(buf []byte) (uint64, bool) {
192	return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
193}
194
195func direntNamlen(buf []byte) (uint64, bool) {
196	reclen, ok := direntReclen(buf)
197	if !ok {
198		return 0, false
199	}
200	return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
201}
202
203func Gettimeofday(tv *Timeval) (err error) {
204	err = gettimeofday(tv, nil)
205	return
206}
207
208// TODO
209func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
210	return -1, ENOSYS
211}
212
213//sys	getdirent(fd int, buf []byte) (n int, err error)
214
215func ReadDirent(fd int, buf []byte) (n int, err error) {
216	return getdirent(fd, buf)
217}
218
219//sys  wait4(pid _Pid_t, status *_C_int, options int, rusage *Rusage) (wpid _Pid_t, err error)
220
221func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
222	var status _C_int
223	var r _Pid_t
224	err = ERESTART
225	// AIX wait4 may return with ERESTART errno, while the process is still
226	// active.
227	for err == ERESTART {
228		r, err = wait4(_Pid_t(pid), &status, options, rusage)
229	}
230	wpid = int(r)
231	if wstatus != nil {
232		*wstatus = WaitStatus(status)
233	}
234	return
235}
236
237//sys	fsyncRange(fd int, how int, start int64, length int64) (err error) = fsync_range
238
239func Fsync(fd int) error {
240	return fsyncRange(fd, O_SYNC, 0, 0)
241}
242
243/*
244 * Socket
245 */
246//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
247//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
248//sys   Getkerninfo(op int32, where uintptr, size uintptr, arg int64) (i int32, err error)
249//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
250//sys	Listen(s int, backlog int) (err error)
251//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
252//sys	socket(domain int, typ int, proto int) (fd int, err error)
253//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
254//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
255//sys	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
256//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
257//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
258//sys	Shutdown(s int, how int) (err error)
259
260// In order to use msghdr structure with Control, Controllen in golang.org/x/net,
261// nrecvmsg and nsendmsg must be used.
262//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = nrecvmsg
263//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = nsendmsg
264
265func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
266	if sa.Port < 0 || sa.Port > 0xFFFF {
267		return nil, 0, EINVAL
268	}
269	sa.raw.Family = AF_INET
270	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
271	p[0] = byte(sa.Port >> 8)
272	p[1] = byte(sa.Port)
273	sa.raw.Addr = sa.Addr
274	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
275}
276
277func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
278	if sa.Port < 0 || sa.Port > 0xFFFF {
279		return nil, 0, EINVAL
280	}
281	sa.raw.Family = AF_INET6
282	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
283	p[0] = byte(sa.Port >> 8)
284	p[1] = byte(sa.Port)
285	sa.raw.Scope_id = sa.ZoneId
286	sa.raw.Addr = sa.Addr
287	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
288}
289
290func (sa *RawSockaddrUnix) setLen(n int) {
291	sa.Len = uint8(3 + n) // 2 for Family, Len; 1 for NUL.
292}
293
294func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
295	name := sa.Name
296	n := len(name)
297	if n > len(sa.raw.Path) {
298		return nil, 0, EINVAL
299	}
300	sa.raw.Family = AF_UNIX
301	sa.raw.setLen(n)
302	for i := 0; i < n; i++ {
303		sa.raw.Path[i] = uint8(name[i])
304	}
305	// length is family (uint16), name, NUL.
306	sl := _Socklen(2)
307	if n > 0 {
308		sl += _Socklen(n) + 1
309	}
310
311	return unsafe.Pointer(&sa.raw), sl, nil
312}
313
314func Getsockname(fd int) (sa Sockaddr, err error) {
315	var rsa RawSockaddrAny
316	var len _Socklen = SizeofSockaddrAny
317	if err = getsockname(fd, &rsa, &len); err != nil {
318		return
319	}
320	return anyToSockaddr(&rsa)
321}
322
323//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
324
325func Accept(fd int) (nfd int, sa Sockaddr, err error) {
326	var rsa RawSockaddrAny
327	var len _Socklen = SizeofSockaddrAny
328	nfd, err = accept(fd, &rsa, &len)
329	if err != nil {
330		return
331	}
332	sa, err = anyToSockaddr(&rsa)
333	if err != nil {
334		Close(nfd)
335		nfd = 0
336	}
337	return
338}
339
340func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
341	var msg Msghdr
342	msg.Name = (*byte)(unsafe.Pointer(rsa))
343	msg.Namelen = uint32(SizeofSockaddrAny)
344	var iov Iovec
345	if len(p) > 0 {
346		iov.Base = &p[0]
347		iov.SetLen(len(p))
348	}
349	var dummy byte
350	if len(oob) > 0 {
351		var sockType int
352		sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
353		if err != nil {
354			return
355		}
356		// receive at least one normal byte
357		if sockType != SOCK_DGRAM && len(p) == 0 {
358			iov.Base = &dummy
359			iov.SetLen(1)
360		}
361		msg.Control = &oob[0]
362		msg.SetControllen(len(oob))
363	}
364	msg.Iov = &iov
365	msg.Iovlen = 1
366	if n, err = recvmsg(fd, &msg, flags); err != nil {
367		return
368	}
369	oobn = int(msg.Controllen)
370	recvflags = int(msg.Flags)
371	return
372}
373
374func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
375	var msg Msghdr
376	msg.Name = (*byte)(ptr)
377	msg.Namelen = uint32(salen)
378	var iov Iovec
379	if len(p) > 0 {
380		iov.Base = &p[0]
381		iov.SetLen(len(p))
382	}
383	var dummy byte
384	if len(oob) > 0 {
385		var sockType int
386		sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
387		if err != nil {
388			return 0, err
389		}
390		// send at least one normal byte
391		if sockType != SOCK_DGRAM && len(p) == 0 {
392			iov.Base = &dummy
393			iov.SetLen(1)
394		}
395		msg.Control = &oob[0]
396		msg.SetControllen(len(oob))
397	}
398	msg.Iov = &iov
399	msg.Iovlen = 1
400	if n, err = sendmsg(fd, &msg, flags); err != nil {
401		return 0, err
402	}
403	if len(oob) > 0 && len(p) == 0 {
404		n = 0
405	}
406	return n, nil
407}
408
409func (sa *RawSockaddrUnix) getLen() (int, error) {
410	// Some versions of AIX have a bug in getsockname (see IV78655).
411	// We can't rely on sa.Len being set correctly.
412	n := SizeofSockaddrUnix - 3 // subtract leading Family, Len, terminating NUL.
413	for i := 0; i < n; i++ {
414		if sa.Path[i] == 0 {
415			n = i
416			break
417		}
418	}
419	return n, nil
420}
421
422func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
423	switch rsa.Addr.Family {
424	case AF_UNIX:
425		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
426		sa := new(SockaddrUnix)
427		n, err := pp.getLen()
428		if err != nil {
429			return nil, err
430		}
431		sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
432		return sa, nil
433
434	case AF_INET:
435		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
436		sa := new(SockaddrInet4)
437		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
438		sa.Port = int(p[0])<<8 + int(p[1])
439		sa.Addr = pp.Addr
440		return sa, nil
441
442	case AF_INET6:
443		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
444		sa := new(SockaddrInet6)
445		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
446		sa.Port = int(p[0])<<8 + int(p[1])
447		sa.Addr = pp.Addr
448		return sa, nil
449	}
450	return nil, EAFNOSUPPORT
451}
452
453type SockaddrDatalink struct {
454	Len    uint8
455	Family uint8
456	Index  uint16
457	Type   uint8
458	Nlen   uint8
459	Alen   uint8
460	Slen   uint8
461	Data   [120]uint8
462	raw    RawSockaddrDatalink
463}
464
465/*
466 * Wait
467 */
468
469type WaitStatus uint32
470
471func (w WaitStatus) Stopped() bool { return w&0x40 != 0 }
472func (w WaitStatus) StopSignal() Signal {
473	if !w.Stopped() {
474		return -1
475	}
476	return Signal(w>>8) & 0xFF
477}
478
479func (w WaitStatus) Exited() bool { return w&0xFF == 0 }
480func (w WaitStatus) ExitStatus() int {
481	if !w.Exited() {
482		return -1
483	}
484	return int((w >> 8) & 0xFF)
485}
486
487func (w WaitStatus) Signaled() bool { return w&0x40 == 0 && w&0xFF != 0 }
488func (w WaitStatus) Signal() Signal {
489	if !w.Signaled() {
490		return -1
491	}
492	return Signal(w>>16) & 0xFF
493}
494
495func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 }
496
497func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 }
498
499func (w WaitStatus) TrapCause() int { return -1 }
500
501/*
502 * ptrace
503 */
504
505//sys	Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
506//sys	ptrace64(request int, id int64, addr int64, data int, buff uintptr) (err error)
507//sys	ptrace64Ptr(request int, id int64, addr int64, data int, buff unsafe.Pointer) (err error) = ptrace64
508
509func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno {
510	if request == PTRACE_TRACEME {
511		// Convert to AIX ptrace call.
512		err := ptrace64(PT_TRACE_ME, 0, 0, 0, 0)
513		if err != nil {
514			return err.(Errno)
515		}
516		return 0
517	}
518	return ENOSYS
519}
520
521func ptracePeek(pid int, addr uintptr, out []byte) (count int, err error) {
522	n := 0
523	for len(out) > 0 {
524		bsize := len(out)
525		if bsize > 1024 {
526			bsize = 1024
527		}
528		err = ptrace64Ptr(PT_READ_BLOCK, int64(pid), int64(addr), bsize, unsafe.Pointer(&out[0]))
529		if err != nil {
530			return 0, err
531		}
532		addr += uintptr(bsize)
533		n += bsize
534		out = out[n:]
535	}
536	return n, nil
537}
538
539func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) {
540	return ptracePeek(pid, addr, out)
541}
542
543func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
544	return ptracePeek(pid, addr, out)
545}
546
547func ptracePoke(pid int, addr uintptr, data []byte) (count int, err error) {
548	n := 0
549	for len(data) > 0 {
550		bsize := len(data)
551		if bsize > 1024 {
552			bsize = 1024
553		}
554		err = ptrace64Ptr(PT_WRITE_BLOCK, int64(pid), int64(addr), bsize, unsafe.Pointer(&data[0]))
555		if err != nil {
556			return 0, err
557		}
558		addr += uintptr(bsize)
559		n += bsize
560		data = data[n:]
561	}
562	return n, nil
563}
564
565func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
566	return ptracePoke(pid, addr, data)
567}
568
569func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
570	return ptracePoke(pid, addr, data)
571}
572
573func PtraceCont(pid int, signal int) (err error) {
574	return ptrace64(PT_CONTINUE, int64(pid), 1, signal, 0)
575}
576
577func PtraceSingleStep(pid int) (err error) { return ptrace64(PT_STEP, int64(pid), 1, 0, 0) }
578
579func PtraceAttach(pid int) (err error) { return ptrace64(PT_ATTACH, int64(pid), 0, 0, 0) }
580
581func PtraceDetach(pid int) (err error) { return ptrace64(PT_DETACH, int64(pid), 0, 0, 0) }
582
583/*
584 * Direct access
585 */
586
587//sys	Acct(path string) (err error)
588//sys	Chdir(path string) (err error)
589//sys	Chmod(path string, mode uint32) (err error)
590//sys	Chown(path string, uid int, gid int) (err error)
591//sys	Chroot(path string) (err error)
592//sys	Close(fd int) (err error)
593//sys	Dup(fd int) (nfd int, err error)
594//sys	Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
595//sys	Fchdir(fd int) (err error)
596//sys	Fchmod(fd int, mode uint32) (err error)
597//sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
598//sys	Fchown(fd int, uid int, gid int) (err error)
599//sys	Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
600//sys	Fpathconf(fd int, name int) (val int, err error)
601//sys	Fstat(fd int, stat *Stat_t) (err error)
602//sys	Fstatfs(fd int, buf *Statfs_t) (err error)
603//sys	Ftruncate(fd int, length int64) (err error)
604//sysnb	Getgid() (gid int)
605//sysnb	Getpid() (pid int)
606//sys	Geteuid() (euid int)
607//sys	Getegid() (egid int)
608//sys	Getppid() (ppid int)
609//sys	Getpriority(which int, who int) (n int, err error)
610//sysnb	Getrlimit(which int, lim *Rlimit) (err error)
611//sysnb	Getrusage(who int, rusage *Rusage) (err error)
612//sysnb	Getuid() (uid int)
613//sys	Kill(pid int, signum Signal) (err error)
614//sys	Lchown(path string, uid int, gid int) (err error)
615//sys	Link(path string, link string) (err error)
616//sys	Lstat(path string, stat *Stat_t) (err error)
617//sys	Mkdir(path string, mode uint32) (err error)
618//sys	Mkdirat(dirfd int, path string, mode uint32) (err error)
619//sys	Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
620//sys	Open(path string, mode int, perm uint32) (fd int, err error)
621//sys	pread(fd int, p []byte, offset int64) (n int, err error)
622//sys	pwrite(fd int, p []byte, offset int64) (n int, err error)
623//sys	read(fd int, p []byte) (n int, err error)
624//sys	Reboot(how int) (err error)
625//sys	Rename(from string, to string) (err error)
626//sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
627//sys	Rmdir(path string) (err error)
628//sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
629//sysnb	Setegid(egid int) (err error)
630//sysnb	Seteuid(euid int) (err error)
631//sysnb	Setgid(gid int) (err error)
632//sysnb	Setuid(uid int) (err error)
633//sysnb	Setpgid(pid int, pgid int) (err error)
634//sys	Setpriority(which int, who int, prio int) (err error)
635//sysnb	Setregid(rgid int, egid int) (err error)
636//sysnb	Setreuid(ruid int, euid int) (err error)
637//sysnb	setrlimit(which int, lim *Rlimit) (err error)
638//sys	Stat(path string, stat *Stat_t) (err error)
639//sys	Statfs(path string, buf *Statfs_t) (err error)
640//sys	Symlink(path string, link string) (err error)
641//sys	Truncate(path string, length int64) (err error)
642//sys	Umask(newmask int) (oldmask int)
643//sys	Unlink(path string) (err error)
644//sysnb	Uname(buf *Utsname) (err error)
645//sys	write(fd int, p []byte) (n int, err error)
646//sys	writev(fd int, iovecs []Iovec) (n uintptr, err error)
647
648//sys	gettimeofday(tv *Timeval, tzp *Timezone) (err error)
649
650func setTimespec(sec, nsec int64) Timespec {
651	return Timespec{Sec: sec, Nsec: nsec}
652}
653
654func setTimeval(sec, usec int64) Timeval {
655	return Timeval{Sec: sec, Usec: int32(usec)}
656}
657
658func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
659	r0, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_read)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
660	n = int(r0)
661	if e1 != 0 {
662		err = e1
663	}
664	return
665}
666
667/*
668 * Map
669 */
670
671var mapper = &mmapper{
672	active: make(map[*byte][]byte),
673	mmap:   mmap,
674	munmap: munmap,
675}
676
677//sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
678//sys	munmap(addr uintptr, length uintptr) (err error)
679
680func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
681	return mapper.Mmap(fd, offset, length, prot, flags)
682}
683
684func Munmap(b []byte) (err error) {
685	return mapper.Munmap(b)
686}
687