syscall_solaris.mx raw

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