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