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