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