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