Source file src/syscall/syscall_solaris.go

     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  // Solaris 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 wrap
    10  // it in our own nicer implementation, either here or in
    11  // syscall_solaris.go or syscall_unix.go.
    12  
    13  package syscall
    14  
    15  import "unsafe"
    16  
    17  const _F_DUP2FD_CLOEXEC = F_DUP2FD_CLOEXEC
    18  
    19  func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
    20  func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
    21  func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
    22  func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
    23  
    24  // Implemented in asm_solaris_amd64.s.
    25  //
    26  // Accessed via assembly in x/sys/unix.
    27  //
    28  //go:linkname rawSysvicall6
    29  func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
    30  
    31  // Accessed via assembly in x/sys/unix and x/net/lif.
    32  //
    33  //go:linkname sysvicall6
    34  func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
    35  
    36  type SockaddrDatalink struct {
    37  	Family uint16
    38  	Index  uint16
    39  	Type   uint8
    40  	Nlen   uint8
    41  	Alen   uint8
    42  	Slen   uint8
    43  	Data   [244]int8
    44  	raw    RawSockaddrDatalink
    45  }
    46  
    47  func direntIno(buf []byte) (uint64, bool) {
    48  	return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
    49  }
    50  
    51  func direntReclen(buf []byte) (uint64, bool) {
    52  	return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
    53  }
    54  
    55  func direntNamlen(buf []byte) (uint64, bool) {
    56  	reclen, ok := direntReclen(buf)
    57  	if !ok {
    58  		return 0, false
    59  	}
    60  	return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
    61  }
    62  
    63  func Pipe(p []int) (err error) {
    64  	return Pipe2(p, 0)
    65  }
    66  
    67  //sysnb	pipe2(p *[2]_C_int, flags int) (err error)
    68  
    69  func Pipe2(p []int, flags int) error {
    70  	if len(p) != 2 {
    71  		return EINVAL
    72  	}
    73  	var pp [2]_C_int
    74  	err := pipe2(&pp, flags)
    75  	if err == nil {
    76  		p[0] = int(pp[0])
    77  		p[1] = int(pp[1])
    78  	}
    79  	return err
    80  }
    81  
    82  //go:cgo_ldflag "-lxnet"
    83  //go:cgo_ldflag "-lsocket"
    84  
    85  //sys   accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = libsocket.accept4
    86  
    87  func Accept4(fd int, flags int) (int, Sockaddr, error) {
    88  	var rsa RawSockaddrAny
    89  	var addrlen _Socklen = SizeofSockaddrAny
    90  	nfd, err := accept4(fd, &rsa, &addrlen, flags)
    91  	if err != nil {
    92  		return 0, nil, err
    93  	}
    94  	if addrlen > SizeofSockaddrAny {
    95  		panic("RawSockaddrAny too small")
    96  	}
    97  	sa, err := anyToSockaddr(&rsa)
    98  	if err != nil {
    99  		Close(nfd)
   100  		return 0, nil, err
   101  	}
   102  	return nfd, sa, nil
   103  }
   104  
   105  func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
   106  	if sa.Port < 0 || sa.Port > 0xFFFF {
   107  		return nil, 0, EINVAL
   108  	}
   109  	sa.raw.Family = AF_INET
   110  	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
   111  	p[0] = byte(sa.Port >> 8)
   112  	p[1] = byte(sa.Port)
   113  	sa.raw.Addr = sa.Addr
   114  	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
   115  }
   116  
   117  func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
   118  	if sa.Port < 0 || sa.Port > 0xFFFF {
   119  		return nil, 0, EINVAL
   120  	}
   121  	sa.raw.Family = AF_INET6
   122  	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
   123  	p[0] = byte(sa.Port >> 8)
   124  	p[1] = byte(sa.Port)
   125  	sa.raw.Scope_id = sa.ZoneId
   126  	sa.raw.Addr = sa.Addr
   127  	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
   128  }
   129  
   130  func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
   131  	name := sa.Name
   132  	n := len(name)
   133  	if n >= len(sa.raw.Path) {
   134  		return nil, 0, EINVAL
   135  	}
   136  	sa.raw.Family = AF_UNIX
   137  	for i := 0; i < n; i++ {
   138  		sa.raw.Path[i] = int8(name[i])
   139  	}
   140  	// length is family (uint16), name, NUL.
   141  	sl := _Socklen(2)
   142  	if n > 0 {
   143  		sl += _Socklen(n) + 1
   144  	}
   145  	if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
   146  		// Check sl > 3 so we don't change unnamed socket behavior.
   147  		sa.raw.Path[0] = 0
   148  		// Don't count trailing NUL for abstract address.
   149  		sl--
   150  	}
   151  
   152  	return unsafe.Pointer(&sa.raw), sl, nil
   153  }
   154  
   155  func Getsockname(fd int) (sa Sockaddr, err error) {
   156  	var rsa RawSockaddrAny
   157  	var len _Socklen = SizeofSockaddrAny
   158  	if err = getsockname(fd, &rsa, &len); err != nil {
   159  		return
   160  	}
   161  	return anyToSockaddr(&rsa)
   162  }
   163  
   164  const ImplementsGetwd = true
   165  
   166  //sys	Getcwd(buf []byte) (n int, err error)
   167  
   168  func Getwd() (wd string, err error) {
   169  	var buf [PathMax]byte
   170  	// Getcwd will return an error if it failed for any reason.
   171  	_, err = Getcwd(buf[0:])
   172  	if err != nil {
   173  		return "", err
   174  	}
   175  	n := clen(buf[:])
   176  	if n < 1 {
   177  		return "", EINVAL
   178  	}
   179  	return string(buf[:n]), nil
   180  }
   181  
   182  /*
   183   * Wrapped
   184   */
   185  
   186  //sysnb	getgroups(ngid int, gid *_Gid_t) (n int, err error)
   187  //sysnb	setgroups(ngid int, gid *_Gid_t) (err error)
   188  
   189  func Getgroups() (gids []int, err error) {
   190  	n, err := getgroups(0, nil)
   191  	if err != nil {
   192  		return nil, err
   193  	}
   194  	if n == 0 {
   195  		return nil, nil
   196  	}
   197  
   198  	// Sanity check group count. Max is 16 on BSD.
   199  	if n < 0 || n > 1000 {
   200  		return nil, EINVAL
   201  	}
   202  
   203  	a := make([]_Gid_t, n)
   204  	n, err = getgroups(n, &a[0])
   205  	if err != nil {
   206  		return nil, err
   207  	}
   208  	gids = make([]int, n)
   209  	for i, v := range a[0:n] {
   210  		gids[i] = int(v)
   211  	}
   212  	return
   213  }
   214  
   215  func Setgroups(gids []int) (err error) {
   216  	if len(gids) == 0 {
   217  		return setgroups(0, nil)
   218  	}
   219  
   220  	a := make([]_Gid_t, len(gids))
   221  	for i, v := range gids {
   222  		a[i] = _Gid_t(v)
   223  	}
   224  	return setgroups(len(a), &a[0])
   225  }
   226  
   227  func ReadDirent(fd int, buf []byte) (n int, err error) {
   228  	// Final argument is (basep *uintptr) and the syscall doesn't take nil.
   229  	// TODO(rsc): Can we use a single global basep for all calls?
   230  	return Getdents(fd, buf, new(uintptr))
   231  }
   232  
   233  // Wait status is 7 bits at bottom, either 0 (exited),
   234  // 0x7F (stopped), or a signal number that caused an exit.
   235  // The 0x80 bit is whether there was a core dump.
   236  // An extra number (exit code, signal causing a stop)
   237  // is in the high bits.
   238  
   239  type WaitStatus uint32
   240  
   241  const (
   242  	mask  = 0x7F
   243  	core  = 0x80
   244  	shift = 8
   245  
   246  	exited  = 0
   247  	stopped = 0x7F
   248  )
   249  
   250  func (w WaitStatus) Exited() bool { return w&mask == exited }
   251  
   252  func (w WaitStatus) ExitStatus() int {
   253  	if w&mask != exited {
   254  		return -1
   255  	}
   256  	return int(w >> shift)
   257  }
   258  
   259  func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
   260  
   261  func (w WaitStatus) Signal() Signal {
   262  	sig := Signal(w & mask)
   263  	if sig == stopped || sig == 0 {
   264  		return -1
   265  	}
   266  	return sig
   267  }
   268  
   269  func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
   270  
   271  func (w WaitStatus) Stopped() bool { return w&mask == stopped && Signal(w>>shift) != SIGSTOP }
   272  
   273  func (w WaitStatus) Continued() bool { return w&mask == stopped && Signal(w>>shift) == SIGSTOP }
   274  
   275  func (w WaitStatus) StopSignal() Signal {
   276  	if !w.Stopped() {
   277  		return -1
   278  	}
   279  	return Signal(w>>shift) & 0xFF
   280  }
   281  
   282  func (w WaitStatus) TrapCause() int { return -1 }
   283  
   284  func wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid uintptr, err uintptr)
   285  
   286  func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
   287  	r0, e1 := wait4(uintptr(pid), wstatus, uintptr(options), rusage)
   288  	if e1 != 0 {
   289  		err = Errno(e1)
   290  	}
   291  	return int(r0), err
   292  }
   293  
   294  func gethostname() (name string, err uintptr)
   295  
   296  func Gethostname() (name string, err error) {
   297  	name, e1 := gethostname()
   298  	if e1 != 0 {
   299  		err = Errno(e1)
   300  	}
   301  	return name, err
   302  }
   303  
   304  func UtimesNano(path string, ts []Timespec) error {
   305  	if len(ts) != 2 {
   306  		return EINVAL
   307  	}
   308  	return utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
   309  }
   310  
   311  //sys	fcntl(fd int, cmd int, arg int) (val int, err error)
   312  
   313  // FcntlFlock performs a fcntl syscall for the [F_GETLK], [F_SETLK] or [F_SETLKW] command.
   314  func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
   315  	_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_fcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
   316  	if e1 != 0 {
   317  		return e1
   318  	}
   319  	return nil
   320  }
   321  
   322  func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
   323  	switch rsa.Addr.Family {
   324  	case AF_UNIX:
   325  		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
   326  		sa := new(SockaddrUnix)
   327  		// Assume path ends at NUL.
   328  		// This is not technically the Solaris semantics for
   329  		// abstract Unix domain sockets -- they are supposed
   330  		// to be uninterpreted fixed-size binary blobs -- but
   331  		// everyone uses this convention.
   332  		n := 0
   333  		for n < len(pp.Path) && pp.Path[n] != 0 {
   334  			n++
   335  		}
   336  		sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
   337  		return sa, nil
   338  
   339  	case AF_INET:
   340  		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
   341  		sa := new(SockaddrInet4)
   342  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   343  		sa.Port = int(p[0])<<8 + int(p[1])
   344  		sa.Addr = pp.Addr
   345  		return sa, nil
   346  
   347  	case AF_INET6:
   348  		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
   349  		sa := new(SockaddrInet6)
   350  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   351  		sa.Port = int(p[0])<<8 + int(p[1])
   352  		sa.ZoneId = pp.Scope_id
   353  		sa.Addr = pp.Addr
   354  		return sa, nil
   355  	}
   356  	return nil, EAFNOSUPPORT
   357  }
   358  
   359  //sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept
   360  
   361  func Accept(fd int) (nfd int, sa Sockaddr, err error) {
   362  	var rsa RawSockaddrAny
   363  	var len _Socklen = SizeofSockaddrAny
   364  	nfd, err = accept(fd, &rsa, &len)
   365  	if err != nil {
   366  		return
   367  	}
   368  	sa, err = anyToSockaddr(&rsa)
   369  	if err != nil {
   370  		Close(nfd)
   371  		nfd = 0
   372  	}
   373  	return
   374  }
   375  
   376  func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
   377  	var msg Msghdr
   378  	msg.Name = (*byte)(unsafe.Pointer(rsa))
   379  	msg.Namelen = uint32(SizeofSockaddrAny)
   380  	var iov Iovec
   381  	if len(p) > 0 {
   382  		iov.Base = (*int8)(unsafe.Pointer(&p[0]))
   383  		iov.SetLen(len(p))
   384  	}
   385  	var dummy int8
   386  	if len(oob) > 0 {
   387  		// receive at least one normal byte
   388  		if len(p) == 0 {
   389  			iov.Base = &dummy
   390  			iov.SetLen(1)
   391  		}
   392  		msg.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
   393  		msg.Accrightslen = int32(len(oob))
   394  	}
   395  	msg.Iov = &iov
   396  	msg.Iovlen = 1
   397  	if n, err = recvmsg(fd, &msg, flags); err != nil {
   398  		return
   399  	}
   400  	oobn = int(msg.Accrightslen)
   401  	return
   402  }
   403  
   404  //sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
   405  
   406  func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
   407  	var msg Msghdr
   408  	msg.Name = (*byte)(unsafe.Pointer(ptr))
   409  	msg.Namelen = uint32(salen)
   410  	var iov Iovec
   411  	if len(p) > 0 {
   412  		iov.Base = (*int8)(unsafe.Pointer(&p[0]))
   413  		iov.SetLen(len(p))
   414  	}
   415  	var dummy int8
   416  	if len(oob) > 0 {
   417  		// send at least one normal byte
   418  		if len(p) == 0 {
   419  			iov.Base = &dummy
   420  			iov.SetLen(1)
   421  		}
   422  		msg.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
   423  		msg.Accrightslen = int32(len(oob))
   424  	}
   425  	msg.Iov = &iov
   426  	msg.Iovlen = 1
   427  	if n, err = sendmsg(fd, &msg, flags); err != nil {
   428  		return 0, err
   429  	}
   430  	if len(oob) > 0 && len(p) == 0 {
   431  		n = 0
   432  	}
   433  	return n, nil
   434  }
   435  
   436  /*
   437   * Exposed directly
   438   */
   439  //sys	Access(path string, mode uint32) (err error)
   440  //sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
   441  //sys	Chdir(path string) (err error)
   442  //sys	Chmod(path string, mode uint32) (err error)
   443  //sys	Chown(path string, uid int, gid int) (err error)
   444  //sys	Chroot(path string) (err error)
   445  //sys	Close(fd int) (err error)
   446  //sys	Dup(fd int) (nfd int, err error)
   447  //sys	Fchdir(fd int) (err error)
   448  //sys	Fchmod(fd int, mode uint32) (err error)
   449  //sys	Fchown(fd int, uid int, gid int) (err error)
   450  //sys	Fpathconf(fd int, name int) (val int, err error)
   451  //sys	Fstat(fd int, stat *Stat_t) (err error)
   452  //sys	Getdents(fd int, buf []byte, basep *uintptr) (n int, err error)
   453  //sysnb	Getgid() (gid int)
   454  //sysnb	Getpid() (pid int)
   455  //sys	Geteuid() (euid int)
   456  //sys	Getegid() (egid int)
   457  //sys	Getppid() (ppid int)
   458  //sys	Getpriority(which int, who int) (n int, err error)
   459  //sysnb	Getrlimit(which int, lim *Rlimit) (err error)
   460  //sysnb	Getrusage(who int, rusage *Rusage) (err error)
   461  //sysnb	Gettimeofday(tv *Timeval) (err error)
   462  //sysnb	Getuid() (uid int)
   463  //sys	Kill(pid int, signum Signal) (err error)
   464  //sys	Lchown(path string, uid int, gid int) (err error)
   465  //sys	Link(path string, link string) (err error)
   466  //sys	Listen(s int, backlog int) (err error) = libsocket.__xnet_listen
   467  //sys	Lstat(path string, stat *Stat_t) (err error)
   468  //sys	Mkdir(path string, mode uint32) (err error)
   469  //sys	Mknod(path string, mode uint32, dev int) (err error)
   470  //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
   471  //sys	Open(path string, mode int, perm uint32) (fd int, err error)
   472  //sys	Pathconf(path string, name int) (val int, err error)
   473  //sys	pread(fd int, p []byte, offset int64) (n int, err error)
   474  //sys	pwrite(fd int, p []byte, offset int64) (n int, err error)
   475  //sys	read(fd int, p []byte) (n int, err error)
   476  //sys	Readlink(path string, buf []byte) (n int, err error)
   477  //sys	Rename(from string, to string) (err error)
   478  //sys	Rmdir(path string) (err error)
   479  //sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
   480  //sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile
   481  //sysnb	Setegid(egid int) (err error)
   482  //sysnb	Seteuid(euid int) (err error)
   483  //sysnb	Setgid(gid int) (err error)
   484  //sysnb	Setpgid(pid int, pgid int) (err error)
   485  //sys	Setpriority(which int, who int, prio int) (err error)
   486  //sysnb	Setregid(rgid int, egid int) (err error)
   487  //sysnb	Setreuid(ruid int, euid int) (err error)
   488  //sysnb	setrlimit(which int, lim *Rlimit) (err error)
   489  //sysnb	Setsid() (pid int, err error)
   490  //sysnb	Setuid(uid int) (err error)
   491  //sys	Shutdown(s int, how int) (err error) = libsocket.shutdown
   492  //sys	Stat(path string, stat *Stat_t) (err error)
   493  //sys	Symlink(path string, link string) (err error)
   494  //sys	Sync() (err error)
   495  //sys	Truncate(path string, length int64) (err error)
   496  //sys	Fsync(fd int) (err error)
   497  //sys	Ftruncate(fd int, length int64) (err error)
   498  //sys	Umask(newmask int) (oldmask int)
   499  //sys	Unlink(path string) (err error)
   500  //sys	utimes(path string, times *[2]Timeval) (err error)
   501  //sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind
   502  //sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect
   503  //sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
   504  //sys	munmap(addr uintptr, length uintptr) (err error)
   505  //sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto
   506  //sys	socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket
   507  //sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair
   508  //sys	write(fd int, p []byte) (n int, err error)
   509  //sys	writev(fd int, iovecs []Iovec) (n uintptr, err error)
   510  //sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt
   511  //sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername
   512  //sys	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname
   513  //sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt
   514  //sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
   515  //sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
   516  //sys	getexecname() (path unsafe.Pointer, err error) = libc.getexecname
   517  //sys	utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error)
   518  
   519  func Getexecname() (path string, err error) {
   520  	ptr, err := getexecname()
   521  	if err != nil {
   522  		return "", err
   523  	}
   524  	bytes := (*[1 << 29]byte)(ptr)[:]
   525  	for i, b := range bytes {
   526  		if b == 0 {
   527  			return string(bytes[:i]), nil
   528  		}
   529  	}
   530  	panic("unreachable")
   531  }
   532  
   533  func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
   534  	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_read)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
   535  	n = int(r0)
   536  	if e1 != 0 {
   537  		err = e1
   538  	}
   539  	return
   540  }
   541  
   542  var mapper = &mmapper{
   543  	active: make(map[*byte][]byte),
   544  	mmap:   mmap,
   545  	munmap: munmap,
   546  }
   547  
   548  func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
   549  	return mapper.Mmap(fd, offset, length, prot, flags)
   550  }
   551  
   552  func Munmap(b []byte) (err error) {
   553  	return mapper.Munmap(b)
   554  }
   555  
   556  func Utimes(path string, tv []Timeval) error {
   557  	if len(tv) != 2 {
   558  		return EINVAL
   559  	}
   560  	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
   561  }
   562  

View as plain text