Home | History | Annotate | Download | only in syscall
      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 }
    547