Home | History | Annotate | Download | only in unix
      1 // Copyright 2009 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 // +build darwin dragonfly freebsd netbsd openbsd
      6 
      7 // BSD system call wrappers shared by *BSD based systems
      8 // including OS X (Darwin) and FreeBSD.  Like the other
      9 // syscall_*.go files it is compiled as Go code but also
     10 // used as input to mksyscall which parses the //sys
     11 // lines and generates system call stubs.
     12 
     13 package unix
     14 
     15 import (
     16 	"runtime"
     17 	"syscall"
     18 	"unsafe"
     19 )
     20 
     21 /*
     22  * Wrapped
     23  */
     24 
     25 //sysnb	getgroups(ngid int, gid *_Gid_t) (n int, err error)
     26 //sysnb	setgroups(ngid int, gid *_Gid_t) (err error)
     27 
     28 func Getgroups() (gids []int, err error) {
     29 	n, err := getgroups(0, nil)
     30 	if err != nil {
     31 		return nil, err
     32 	}
     33 	if n == 0 {
     34 		return nil, nil
     35 	}
     36 
     37 	// Sanity check group count. Max is 16 on BSD.
     38 	if n < 0 || n > 1000 {
     39 		return nil, EINVAL
     40 	}
     41 
     42 	a := make([]_Gid_t, n)
     43 	n, err = getgroups(n, &a[0])
     44 	if err != nil {
     45 		return nil, err
     46 	}
     47 	gids = make([]int, n)
     48 	for i, v := range a[0:n] {
     49 		gids[i] = int(v)
     50 	}
     51 	return
     52 }
     53 
     54 func Setgroups(gids []int) (err error) {
     55 	if len(gids) == 0 {
     56 		return setgroups(0, nil)
     57 	}
     58 
     59 	a := make([]_Gid_t, len(gids))
     60 	for i, v := range gids {
     61 		a[i] = _Gid_t(v)
     62 	}
     63 	return setgroups(len(a), &a[0])
     64 }
     65 
     66 func ReadDirent(fd int, buf []byte) (n int, err error) {
     67 	// Final argument is (basep *uintptr) and the syscall doesn't take nil.
     68 	// 64 bits should be enough. (32 bits isn't even on 386). Since the
     69 	// actual system call is getdirentries64, 64 is a good guess.
     70 	// TODO(rsc): Can we use a single global basep for all calls?
     71 	var base = (*uintptr)(unsafe.Pointer(new(uint64)))
     72 	return Getdirentries(fd, buf, base)
     73 }
     74 
     75 // Wait status is 7 bits at bottom, either 0 (exited),
     76 // 0x7F (stopped), or a signal number that caused an exit.
     77 // The 0x80 bit is whether there was a core dump.
     78 // An extra number (exit code, signal causing a stop)
     79 // is in the high bits.
     80 
     81 type WaitStatus uint32
     82 
     83 const (
     84 	mask  = 0x7F
     85 	core  = 0x80
     86 	shift = 8
     87 
     88 	exited  = 0
     89 	stopped = 0x7F
     90 )
     91 
     92 func (w WaitStatus) Exited() bool { return w&mask == exited }
     93 
     94 func (w WaitStatus) ExitStatus() int {
     95 	if w&mask != exited {
     96 		return -1
     97 	}
     98 	return int(w >> shift)
     99 }
    100 
    101 func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
    102 
    103 func (w WaitStatus) Signal() syscall.Signal {
    104 	sig := syscall.Signal(w & mask)
    105 	if sig == stopped || sig == 0 {
    106 		return -1
    107 	}
    108 	return sig
    109 }
    110 
    111 func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
    112 
    113 func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
    114 
    115 func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
    116 
    117 func (w WaitStatus) StopSignal() syscall.Signal {
    118 	if !w.Stopped() {
    119 		return -1
    120 	}
    121 	return syscall.Signal(w>>shift) & 0xFF
    122 }
    123 
    124 func (w WaitStatus) TrapCause() int { return -1 }
    125 
    126 //sys	wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error)
    127 
    128 func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
    129 	var status _C_int
    130 	wpid, err = wait4(pid, &status, options, rusage)
    131 	if wstatus != nil {
    132 		*wstatus = WaitStatus(status)
    133 	}
    134 	return
    135 }
    136 
    137 //sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
    138 //sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
    139 //sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
    140 //sysnb	socket(domain int, typ int, proto int) (fd int, err error)
    141 //sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
    142 //sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
    143 //sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
    144 //sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
    145 //sys	Shutdown(s int, how int) (err error)
    146 
    147 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
    148 	if sa.Port < 0 || sa.Port > 0xFFFF {
    149 		return nil, 0, EINVAL
    150 	}
    151 	sa.raw.Len = SizeofSockaddrInet4
    152 	sa.raw.Family = AF_INET
    153 	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
    154 	p[0] = byte(sa.Port >> 8)
    155 	p[1] = byte(sa.Port)
    156 	for i := 0; i < len(sa.Addr); i++ {
    157 		sa.raw.Addr[i] = sa.Addr[i]
    158 	}
    159 	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
    160 }
    161 
    162 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
    163 	if sa.Port < 0 || sa.Port > 0xFFFF {
    164 		return nil, 0, EINVAL
    165 	}
    166 	sa.raw.Len = SizeofSockaddrInet6
    167 	sa.raw.Family = AF_INET6
    168 	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
    169 	p[0] = byte(sa.Port >> 8)
    170 	p[1] = byte(sa.Port)
    171 	sa.raw.Scope_id = sa.ZoneId
    172 	for i := 0; i < len(sa.Addr); i++ {
    173 		sa.raw.Addr[i] = sa.Addr[i]
    174 	}
    175 	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
    176 }
    177 
    178 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
    179 	name := sa.Name
    180 	n := len(name)
    181 	if n >= len(sa.raw.Path) || n == 0 {
    182 		return nil, 0, EINVAL
    183 	}
    184 	sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
    185 	sa.raw.Family = AF_UNIX
    186 	for i := 0; i < n; i++ {
    187 		sa.raw.Path[i] = int8(name[i])
    188 	}
    189 	return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
    190 }
    191 
    192 func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) {
    193 	if sa.Index == 0 {
    194 		return nil, 0, EINVAL
    195 	}
    196 	sa.raw.Len = sa.Len
    197 	sa.raw.Family = AF_LINK
    198 	sa.raw.Index = sa.Index
    199 	sa.raw.Type = sa.Type
    200 	sa.raw.Nlen = sa.Nlen
    201 	sa.raw.Alen = sa.Alen
    202 	sa.raw.Slen = sa.Slen
    203 	for i := 0; i < len(sa.raw.Data); i++ {
    204 		sa.raw.Data[i] = sa.Data[i]
    205 	}
    206 	return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil
    207 }
    208 
    209 func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
    210 	switch rsa.Addr.Family {
    211 	case AF_LINK:
    212 		pp := (*RawSockaddrDatalink)(unsafe.Pointer(rsa))
    213 		sa := new(SockaddrDatalink)
    214 		sa.Len = pp.Len
    215 		sa.Family = pp.Family
    216 		sa.Index = pp.Index
    217 		sa.Type = pp.Type
    218 		sa.Nlen = pp.Nlen
    219 		sa.Alen = pp.Alen
    220 		sa.Slen = pp.Slen
    221 		for i := 0; i < len(sa.Data); i++ {
    222 			sa.Data[i] = pp.Data[i]
    223 		}
    224 		return sa, nil
    225 
    226 	case AF_UNIX:
    227 		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
    228 		if pp.Len < 2 || pp.Len > SizeofSockaddrUnix {
    229 			return nil, EINVAL
    230 		}
    231 		sa := new(SockaddrUnix)
    232 
    233 		// Some BSDs include the trailing NUL in the length, whereas
    234 		// others do not. Work around this by subtracting the leading
    235 		// family and len. The path is then scanned to see if a NUL
    236 		// terminator still exists within the length.
    237 		n := int(pp.Len) - 2 // subtract leading Family, Len
    238 		for i := 0; i < n; i++ {
    239 			if pp.Path[i] == 0 {
    240 				// found early NUL; assume Len included the NUL
    241 				// or was overestimating.
    242 				n = i
    243 				break
    244 			}
    245 		}
    246 		bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
    247 		sa.Name = string(bytes)
    248 		return sa, nil
    249 
    250 	case AF_INET:
    251 		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
    252 		sa := new(SockaddrInet4)
    253 		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
    254 		sa.Port = int(p[0])<<8 + int(p[1])
    255 		for i := 0; i < len(sa.Addr); i++ {
    256 			sa.Addr[i] = pp.Addr[i]
    257 		}
    258 		return sa, nil
    259 
    260 	case AF_INET6:
    261 		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
    262 		sa := new(SockaddrInet6)
    263 		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
    264 		sa.Port = int(p[0])<<8 + int(p[1])
    265 		sa.ZoneId = pp.Scope_id
    266 		for i := 0; i < len(sa.Addr); i++ {
    267 			sa.Addr[i] = pp.Addr[i]
    268 		}
    269 		return sa, nil
    270 	}
    271 	return nil, EAFNOSUPPORT
    272 }
    273 
    274 func Accept(fd int) (nfd int, sa Sockaddr, err error) {
    275 	var rsa RawSockaddrAny
    276 	var len _Socklen = SizeofSockaddrAny
    277 	nfd, err = accept(fd, &rsa, &len)
    278 	if err != nil {
    279 		return
    280 	}
    281 	if runtime.GOOS == "darwin" && len == 0 {
    282 		// Accepted socket has no address.
    283 		// This is likely due to a bug in xnu kernels,
    284 		// where instead of ECONNABORTED error socket
    285 		// is accepted, but has no address.
    286 		Close(nfd)
    287 		return 0, nil, ECONNABORTED
    288 	}
    289 	sa, err = anyToSockaddr(&rsa)
    290 	if err != nil {
    291 		Close(nfd)
    292 		nfd = 0
    293 	}
    294 	return
    295 }
    296 
    297 func Getsockname(fd int) (sa Sockaddr, err error) {
    298 	var rsa RawSockaddrAny
    299 	var len _Socklen = SizeofSockaddrAny
    300 	if err = getsockname(fd, &rsa, &len); err != nil {
    301 		return
    302 	}
    303 	// TODO(jsing): DragonFly has a "bug" (see issue 3349), which should be
    304 	// reported upstream.
    305 	if runtime.GOOS == "dragonfly" && rsa.Addr.Family == AF_UNSPEC && rsa.Addr.Len == 0 {
    306 		rsa.Addr.Family = AF_UNIX
    307 		rsa.Addr.Len = SizeofSockaddrUnix
    308 	}
    309 	return anyToSockaddr(&rsa)
    310 }
    311 
    312 //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
    313 
    314 // GetsockoptString returns the string value of the socket option opt for the
    315 // socket associated with fd at the given socket level.
    316 func GetsockoptString(fd, level, opt int) (string, error) {
    317 	buf := make([]byte, 256)
    318 	vallen := _Socklen(len(buf))
    319 	err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
    320 	if err != nil {
    321 		return "", err
    322 	}
    323 	return string(buf[:vallen-1]), nil
    324 }
    325 
    326 //sys   recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
    327 //sys   sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
    328 //sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
    329 
    330 func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
    331 	var msg Msghdr
    332 	var rsa RawSockaddrAny
    333 	msg.Name = (*byte)(unsafe.Pointer(&rsa))
    334 	msg.Namelen = uint32(SizeofSockaddrAny)
    335 	var iov Iovec
    336 	if len(p) > 0 {
    337 		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
    338 		iov.SetLen(len(p))
    339 	}
    340 	var dummy byte
    341 	if len(oob) > 0 {
    342 		// receive at least one normal byte
    343 		if len(p) == 0 {
    344 			iov.Base = &dummy
    345 			iov.SetLen(1)
    346 		}
    347 		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
    348 		msg.SetControllen(len(oob))
    349 	}
    350 	msg.Iov = &iov
    351 	msg.Iovlen = 1
    352 	if n, err = recvmsg(fd, &msg, flags); err != nil {
    353 		return
    354 	}
    355 	oobn = int(msg.Controllen)
    356 	recvflags = int(msg.Flags)
    357 	// source address is only specified if the socket is unconnected
    358 	if rsa.Addr.Family != AF_UNSPEC {
    359 		from, err = anyToSockaddr(&rsa)
    360 	}
    361 	return
    362 }
    363 
    364 //sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
    365 
    366 func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
    367 	_, err = SendmsgN(fd, p, oob, to, flags)
    368 	return
    369 }
    370 
    371 func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
    372 	var ptr unsafe.Pointer
    373 	var salen _Socklen
    374 	if to != nil {
    375 		ptr, salen, err = to.sockaddr()
    376 		if err != nil {
    377 			return 0, err
    378 		}
    379 	}
    380 	var msg Msghdr
    381 	msg.Name = (*byte)(unsafe.Pointer(ptr))
    382 	msg.Namelen = uint32(salen)
    383 	var iov Iovec
    384 	if len(p) > 0 {
    385 		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
    386 		iov.SetLen(len(p))
    387 	}
    388 	var dummy byte
    389 	if len(oob) > 0 {
    390 		// send at least one normal byte
    391 		if len(p) == 0 {
    392 			iov.Base = &dummy
    393 			iov.SetLen(1)
    394 		}
    395 		msg.Control = (*byte)(unsafe.Pointer(&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 
    409 //sys	kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error)
    410 
    411 func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, err error) {
    412 	var change, event unsafe.Pointer
    413 	if len(changes) > 0 {
    414 		change = unsafe.Pointer(&changes[0])
    415 	}
    416 	if len(events) > 0 {
    417 		event = unsafe.Pointer(&events[0])
    418 	}
    419 	return kevent(kq, change, len(changes), event, len(events), timeout)
    420 }
    421 
    422 //sys	sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL
    423 
    424 // sysctlmib translates name to mib number and appends any additional args.
    425 func sysctlmib(name string, args ...int) ([]_C_int, error) {
    426 	// Translate name to mib number.
    427 	mib, err := nametomib(name)
    428 	if err != nil {
    429 		return nil, err
    430 	}
    431 
    432 	for _, a := range args {
    433 		mib = append(mib, _C_int(a))
    434 	}
    435 
    436 	return mib, nil
    437 }
    438 
    439 func Sysctl(name string) (string, error) {
    440 	return SysctlArgs(name)
    441 }
    442 
    443 func SysctlArgs(name string, args ...int) (string, error) {
    444 	buf, err := SysctlRaw(name, args...)
    445 	if err != nil {
    446 		return "", err
    447 	}
    448 	n := len(buf)
    449 
    450 	// Throw away terminating NUL.
    451 	if n > 0 && buf[n-1] == '\x00' {
    452 		n--
    453 	}
    454 	return string(buf[0:n]), nil
    455 }
    456 
    457 func SysctlUint32(name string) (uint32, error) {
    458 	return SysctlUint32Args(name)
    459 }
    460 
    461 func SysctlUint32Args(name string, args ...int) (uint32, error) {
    462 	mib, err := sysctlmib(name, args...)
    463 	if err != nil {
    464 		return 0, err
    465 	}
    466 
    467 	n := uintptr(4)
    468 	buf := make([]byte, 4)
    469 	if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil {
    470 		return 0, err
    471 	}
    472 	if n != 4 {
    473 		return 0, EIO
    474 	}
    475 	return *(*uint32)(unsafe.Pointer(&buf[0])), nil
    476 }
    477 
    478 func SysctlUint64(name string, args ...int) (uint64, error) {
    479 	mib, err := sysctlmib(name, args...)
    480 	if err != nil {
    481 		return 0, err
    482 	}
    483 
    484 	n := uintptr(8)
    485 	buf := make([]byte, 8)
    486 	if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil {
    487 		return 0, err
    488 	}
    489 	if n != 8 {
    490 		return 0, EIO
    491 	}
    492 	return *(*uint64)(unsafe.Pointer(&buf[0])), nil
    493 }
    494 
    495 func SysctlRaw(name string, args ...int) ([]byte, error) {
    496 	mib, err := sysctlmib(name, args...)
    497 	if err != nil {
    498 		return nil, err
    499 	}
    500 
    501 	// Find size.
    502 	n := uintptr(0)
    503 	if err := sysctl(mib, nil, &n, nil, 0); err != nil {
    504 		return nil, err
    505 	}
    506 	if n == 0 {
    507 		return nil, nil
    508 	}
    509 
    510 	// Read into buffer of that size.
    511 	buf := make([]byte, n)
    512 	if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil {
    513 		return nil, err
    514 	}
    515 
    516 	// The actual call may return less than the original reported required
    517 	// size so ensure we deal with that.
    518 	return buf[:n], nil
    519 }
    520 
    521 //sys	utimes(path string, timeval *[2]Timeval) (err error)
    522 
    523 func Utimes(path string, tv []Timeval) error {
    524 	if tv == nil {
    525 		return utimes(path, nil)
    526 	}
    527 	if len(tv) != 2 {
    528 		return EINVAL
    529 	}
    530 	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
    531 }
    532 
    533 func UtimesNano(path string, ts []Timespec) error {
    534 	if ts == nil {
    535 		err := utimensat(AT_FDCWD, path, nil, 0)
    536 		if err != ENOSYS {
    537 			return err
    538 		}
    539 		return utimes(path, nil)
    540 	}
    541 	if len(ts) != 2 {
    542 		return EINVAL
    543 	}
    544 	// Darwin setattrlist can set nanosecond timestamps
    545 	err := setattrlistTimes(path, ts, 0)
    546 	if err != ENOSYS {
    547 		return err
    548 	}
    549 	err = utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
    550 	if err != ENOSYS {
    551 		return err
    552 	}
    553 	// Not as efficient as it could be because Timespec and
    554 	// Timeval have different types in the different OSes
    555 	tv := [2]Timeval{
    556 		NsecToTimeval(TimespecToNsec(ts[0])),
    557 		NsecToTimeval(TimespecToNsec(ts[1])),
    558 	}
    559 	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
    560 }
    561 
    562 func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
    563 	if ts == nil {
    564 		return utimensat(dirfd, path, nil, flags)
    565 	}
    566 	if len(ts) != 2 {
    567 		return EINVAL
    568 	}
    569 	err := setattrlistTimes(path, ts, flags)
    570 	if err != ENOSYS {
    571 		return err
    572 	}
    573 	return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
    574 }
    575 
    576 //sys	futimes(fd int, timeval *[2]Timeval) (err error)
    577 
    578 func Futimes(fd int, tv []Timeval) error {
    579 	if tv == nil {
    580 		return futimes(fd, nil)
    581 	}
    582 	if len(tv) != 2 {
    583 		return EINVAL
    584 	}
    585 	return futimes(fd, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
    586 }
    587 
    588 //sys	fcntl(fd int, cmd int, arg int) (val int, err error)
    589 
    590 //sys   poll(fds *PollFd, nfds int, timeout int) (n int, err error)
    591 
    592 func Poll(fds []PollFd, timeout int) (n int, err error) {
    593 	if len(fds) == 0 {
    594 		return poll(nil, 0, timeout)
    595 	}
    596 	return poll(&fds[0], len(fds), timeout)
    597 }
    598 
    599 // TODO: wrap
    600 //	Acct(name nil-string) (err error)
    601 //	Gethostuuid(uuid *byte, timeout *Timespec) (err error)
    602 //	Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, err error)
    603 
    604 var mapper = &mmapper{
    605 	active: make(map[*byte][]byte),
    606 	mmap:   mmap,
    607 	munmap: munmap,
    608 }
    609 
    610 func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
    611 	return mapper.Mmap(fd, offset, length, prot, flags)
    612 }
    613 
    614 func Munmap(b []byte) (err error) {
    615 	return mapper.Munmap(b)
    616 }
    617 
    618 //sys	Madvise(b []byte, behav int) (err error)
    619 //sys	Mlock(b []byte) (err error)
    620 //sys	Mlockall(flags int) (err error)
    621 //sys	Mprotect(b []byte, prot int) (err error)
    622 //sys	Msync(b []byte, flags int) (err error)
    623 //sys	Munlock(b []byte) (err error)
    624 //sys	Munlockall() (err error)
    625