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