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) (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 }
    552