github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/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) (err error) {
   274  	if len(ts) != 2 {
   275  		return EINVAL
   276  	}
   277  	var tv [2]Timeval
   278  	for i := 0; i < 2; i++ {
   279  		tv[i].Sec = ts[i].Sec
   280  		tv[i].Usec = ts[i].Nsec / 1000
   281  	}
   282  	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
   283  }
   284  
   285  //sys	fcntl(fd int, cmd int, arg int) (val int, err error)
   286  
   287  // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
   288  func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
   289  	_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_fcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
   290  	if e1 != 0 {
   291  		return e1
   292  	}
   293  	return nil
   294  }
   295  
   296  func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
   297  	switch rsa.Addr.Family {
   298  	case AF_UNIX:
   299  		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
   300  		sa := new(SockaddrUnix)
   301  		// Assume path ends at NUL.
   302  		// This is not technically the Solaris semantics for
   303  		// abstract Unix domain sockets -- they are supposed
   304  		// to be uninterpreted fixed-size binary blobs -- but
   305  		// everyone uses this convention.
   306  		n := 0
   307  		for n < len(pp.Path) && pp.Path[n] != 0 {
   308  			n++
   309  		}
   310  		bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
   311  		sa.Name = string(bytes)
   312  		return sa, nil
   313  
   314  	case AF_INET:
   315  		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
   316  		sa := new(SockaddrInet4)
   317  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   318  		sa.Port = int(p[0])<<8 + int(p[1])
   319  		for i := 0; i < len(sa.Addr); i++ {
   320  			sa.Addr[i] = pp.Addr[i]
   321  		}
   322  		return sa, nil
   323  
   324  	case AF_INET6:
   325  		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
   326  		sa := new(SockaddrInet6)
   327  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   328  		sa.Port = int(p[0])<<8 + int(p[1])
   329  		sa.ZoneId = pp.Scope_id
   330  		for i := 0; i < len(sa.Addr); i++ {
   331  			sa.Addr[i] = pp.Addr[i]
   332  		}
   333  		return sa, nil
   334  	}
   335  	return nil, EAFNOSUPPORT
   336  }
   337  
   338  //sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept
   339  
   340  func Accept(fd int) (nfd int, sa Sockaddr, err error) {
   341  	var rsa RawSockaddrAny
   342  	var len _Socklen = SizeofSockaddrAny
   343  	nfd, err = accept(fd, &rsa, &len)
   344  	if err != nil {
   345  		return
   346  	}
   347  	sa, err = anyToSockaddr(&rsa)
   348  	if err != nil {
   349  		Close(nfd)
   350  		nfd = 0
   351  	}
   352  	return
   353  }
   354  
   355  func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
   356  	var msg Msghdr
   357  	var rsa RawSockaddrAny
   358  	msg.Name = (*byte)(unsafe.Pointer(&rsa))
   359  	msg.Namelen = uint32(SizeofSockaddrAny)
   360  	var iov Iovec
   361  	if len(p) > 0 {
   362  		iov.Base = (*int8)(unsafe.Pointer(&p[0]))
   363  		iov.SetLen(len(p))
   364  	}
   365  	var dummy int8
   366  	if len(oob) > 0 {
   367  		// receive at least one normal byte
   368  		if len(p) == 0 {
   369  			iov.Base = &dummy
   370  			iov.SetLen(1)
   371  		}
   372  		msg.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
   373  		msg.Accrightslen = int32(len(oob))
   374  	}
   375  	msg.Iov = &iov
   376  	msg.Iovlen = 1
   377  	if n, err = recvmsg(fd, &msg, flags); err != nil {
   378  		return
   379  	}
   380  	oobn = int(msg.Accrightslen)
   381  	// source address is only specified if the socket is unconnected
   382  	if rsa.Addr.Family != AF_UNSPEC {
   383  		from, err = anyToSockaddr(&rsa)
   384  	}
   385  	return
   386  }
   387  
   388  func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
   389  	_, err = SendmsgN(fd, p, oob, to, flags)
   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, to Sockaddr, flags int) (n int, err error) {
   396  	var ptr unsafe.Pointer
   397  	var salen _Socklen
   398  	if to != nil {
   399  		ptr, salen, err = to.sockaddr()
   400  		if err != nil {
   401  			return 0, err
   402  		}
   403  	}
   404  	var msg Msghdr
   405  	msg.Name = (*byte)(unsafe.Pointer(ptr))
   406  	msg.Namelen = uint32(salen)
   407  	var iov Iovec
   408  	if len(p) > 0 {
   409  		iov.Base = (*int8)(unsafe.Pointer(&p[0]))
   410  		iov.SetLen(len(p))
   411  	}
   412  	var dummy int8
   413  	if len(oob) > 0 {
   414  		// send at least one normal byte
   415  		if len(p) == 0 {
   416  			iov.Base = &dummy
   417  			iov.SetLen(1)
   418  		}
   419  		msg.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
   420  		msg.Accrightslen = int32(len(oob))
   421  	}
   422  	msg.Iov = &iov
   423  	msg.Iovlen = 1
   424  	if n, err = sendmsg(fd, &msg, flags); err != nil {
   425  		return 0, err
   426  	}
   427  	if len(oob) > 0 && len(p) == 0 {
   428  		n = 0
   429  	}
   430  	return n, nil
   431  }
   432  
   433  /*
   434   * Exposed directly
   435   */
   436  //sys	Access(path string, mode uint32) (err error)
   437  //sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
   438  //sys	Chdir(path string) (err error)
   439  //sys	Chmod(path string, mode uint32) (err error)
   440  //sys	Chown(path string, uid int, gid int) (err error)
   441  //sys	Chroot(path string) (err error)
   442  //sys	Close(fd int) (err error)
   443  //sys	Dup(fd int) (nfd int, err error)
   444  //sys	Exit(code int)
   445  //sys	Fchdir(fd int) (err error)
   446  //sys	Fchmod(fd int, mode uint32) (err error)
   447  //sys	Fchown(fd int, uid int, gid int) (err error)
   448  //sys	Fpathconf(fd int, name int) (val int, err error)
   449  //sys	Fstat(fd int, stat *Stat_t) (err error)
   450  //sys	Getdents(fd int, buf []byte, basep *uintptr) (n int, err error)
   451  //sysnb	Getgid() (gid int)
   452  //sysnb	Getpid() (pid int)
   453  //sys	Geteuid() (euid int)
   454  //sys	Getegid() (egid int)
   455  //sys	Getppid() (ppid int)
   456  //sys	Getpriority(which int, who int) (n int, err error)
   457  //sysnb	Getrlimit(which int, lim *Rlimit) (err error)
   458  //sysnb	Gettimeofday(tv *Timeval) (err error)
   459  //sysnb	Getuid() (uid int)
   460  //sys	Kill(pid int, signum Signal) (err error)
   461  //sys	Lchown(path string, uid int, gid int) (err error)
   462  //sys	Link(path string, link string) (err error)
   463  //sys	Listen(s int, backlog int) (err error) = libsocket.__xnet_listen
   464  //sys	Lstat(path string, stat *Stat_t) (err error)
   465  //sys	Mkdir(path string, mode uint32) (err error)
   466  //sys	Mknod(path string, mode uint32, dev int) (err error)
   467  //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
   468  //sys	Open(path string, mode int, perm uint32) (fd int, err error)
   469  //sys	Pathconf(path string, name int) (val int, err error)
   470  //sys	Pread(fd int, p []byte, offset int64) (n int, err error)
   471  //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
   472  //sys	read(fd int, p []byte) (n int, err error)
   473  //sys	Readlink(path string, buf []byte) (n int, err error)
   474  //sys	Rename(from string, to string) (err error)
   475  //sys	Rmdir(path string) (err error)
   476  //sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
   477  //sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile
   478  //sysnb	Setegid(egid int) (err error)
   479  //sysnb	Seteuid(euid int) (err error)
   480  //sysnb	Setgid(gid int) (err error)
   481  //sysnb	Setpgid(pid int, pgid int) (err error)
   482  //sys	Setpriority(which int, who int, prio int) (err error)
   483  //sysnb	Setregid(rgid int, egid int) (err error)
   484  //sysnb	Setreuid(ruid int, euid int) (err error)
   485  //sysnb	Setrlimit(which int, lim *Rlimit) (err error)
   486  //sysnb	Setsid() (pid int, err error)
   487  //sysnb	Setuid(uid int) (err error)
   488  //sys	Shutdown(s int, how int) (err error) = libsocket.shutdown
   489  //sys	Stat(path string, stat *Stat_t) (err error)
   490  //sys	Symlink(path string, link string) (err error)
   491  //sys	Sync() (err error)
   492  //sys	Truncate(path string, length int64) (err error)
   493  //sys	Fsync(fd int) (err error)
   494  //sys	Ftruncate(fd int, length int64) (err error)
   495  //sys	Umask(newmask int) (oldmask int)
   496  //sys	Unlink(path string) (err error)
   497  //sys	utimes(path string, times *[2]Timeval) (err error)
   498  //sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind
   499  //sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect
   500  //sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
   501  //sys	munmap(addr uintptr, length uintptr) (err error)
   502  //sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto
   503  //sys	socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket
   504  //sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair
   505  //sys	write(fd int, p []byte) (n int, err error)
   506  //sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt
   507  //sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername
   508  //sys	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname
   509  //sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt
   510  //sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
   511  //sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
   512  //sys	getexecname() (path unsafe.Pointer, err error) = libc.getexecname
   513  
   514  func Getexecname() (path string, err error) {
   515  	ptr, err := getexecname()
   516  	if err != nil {
   517  		return "", err
   518  	}
   519  	bytes := (*[1 << 29]byte)(ptr)[:]
   520  	for i, b := range bytes {
   521  		if b == 0 {
   522  			return string(bytes[:i]), nil
   523  		}
   524  	}
   525  	panic("unreachable")
   526  }
   527  
   528  func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
   529  	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_read)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
   530  	n = int(r0)
   531  	if e1 != 0 {
   532  		err = e1
   533  	}
   534  	return
   535  }
   536  
   537  func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
   538  	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_write)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
   539  	n = int(r0)
   540  	if e1 != 0 {
   541  		err = e1
   542  	}
   543  	return
   544  }
   545  
   546  func Utimes(path string, tv []Timeval) error {
   547  	if len(tv) != 2 {
   548  		return EINVAL
   549  	}
   550  	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
   551  }