github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/syscall/syscall_solaris.go (about)

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