github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/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 type SockaddrDatalink struct { 18 Family uint16 19 Index uint16 20 Type uint8 21 Nlen uint8 22 Alen uint8 23 Slen uint8 24 Data [244]int8 25 raw RawSockaddrDatalink 26 } 27 28 func clen(n []byte) int { 29 for i := 0; i < len(n); i++ { 30 if n[i] == 0 { 31 return i 32 } 33 } 34 return len(n) 35 } 36 37 // ParseDirent parses up to max directory entries in buf, 38 // appending the names to names. It returns the number 39 // bytes consumed from buf, the number of entries added 40 // to names, and the new names slice. 41 func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) { 42 origlen := len(buf) 43 for max != 0 && len(buf) > 0 { 44 dirent := (*Dirent)(unsafe.Pointer(&buf[0])) 45 if dirent.Reclen == 0 { 46 buf = nil 47 break 48 } 49 buf = buf[dirent.Reclen:] 50 if dirent.Ino == 0 { // File absent in directory. 51 continue 52 } 53 bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0])) 54 var name = string(bytes[0:clen(bytes[:])]) 55 if name == "." || name == ".." { // Useless names 56 continue 57 } 58 max-- 59 count++ 60 names = append(names, name) 61 } 62 return origlen - len(buf), count, names 63 } 64 65 func pipe() (r uintptr, w uintptr, err uintptr) 66 67 func Pipe(p []int) (err error) { 68 if len(p) != 2 { 69 return EINVAL 70 } 71 r0, w0, e1 := pipe() 72 if e1 != 0 { 73 err = Errno(e1) 74 } 75 p[0], p[1] = int(r0), int(w0) 76 return 77 } 78 79 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { 80 if sa.Port < 0 || sa.Port > 0xFFFF { 81 return nil, 0, EINVAL 82 } 83 sa.raw.Family = AF_INET 84 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 85 p[0] = byte(sa.Port >> 8) 86 p[1] = byte(sa.Port) 87 for i := 0; i < len(sa.Addr); i++ { 88 sa.raw.Addr[i] = sa.Addr[i] 89 } 90 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil 91 } 92 93 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { 94 if sa.Port < 0 || sa.Port > 0xFFFF { 95 return nil, 0, EINVAL 96 } 97 sa.raw.Family = AF_INET6 98 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 99 p[0] = byte(sa.Port >> 8) 100 p[1] = byte(sa.Port) 101 sa.raw.Scope_id = sa.ZoneId 102 for i := 0; i < len(sa.Addr); i++ { 103 sa.raw.Addr[i] = sa.Addr[i] 104 } 105 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil 106 } 107 108 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { 109 name := sa.Name 110 n := len(name) 111 if n >= len(sa.raw.Path) { 112 return nil, 0, EINVAL 113 } 114 sa.raw.Family = AF_UNIX 115 for i := 0; i < n; i++ { 116 sa.raw.Path[i] = int8(name[i]) 117 } 118 // length is family (uint16), name, NUL. 119 sl := _Socklen(2) 120 if n > 0 { 121 sl += _Socklen(n) + 1 122 } 123 if sa.raw.Path[0] == '@' { 124 sa.raw.Path[0] = 0 125 // Don't count trailing NUL for abstract address. 126 sl-- 127 } 128 129 return unsafe.Pointer(&sa.raw), sl, nil 130 } 131 132 func Getsockname(fd int) (sa Sockaddr, err error) { 133 var rsa RawSockaddrAny 134 var len _Socklen = SizeofSockaddrAny 135 if err = getsockname(fd, &rsa, &len); err != nil { 136 return 137 } 138 return anyToSockaddr(&rsa) 139 } 140 141 // The const provides a compile-time constant so clients 142 // can adjust to whether there is a working Getwd and avoid 143 // even linking this function into the binary. See ../os/getwd.go. 144 const ImplementsGetwd = false 145 146 func Getwd() (string, error) { return "", ENOTSUP } 147 148 /* 149 * Wrapped 150 */ 151 152 //sysnb getgroups(ngid int, gid *_Gid_t) (n int, err error) 153 //sysnb setgroups(ngid int, gid *_Gid_t) (err error) 154 155 func Getgroups() (gids []int, err error) { 156 n, err := getgroups(0, nil) 157 if err != nil { 158 return nil, err 159 } 160 if n == 0 { 161 return nil, nil 162 } 163 164 // Sanity check group count. Max is 16 on BSD. 165 if n < 0 || n > 1000 { 166 return nil, EINVAL 167 } 168 169 a := make([]_Gid_t, n) 170 n, err = getgroups(n, &a[0]) 171 if err != nil { 172 return nil, err 173 } 174 gids = make([]int, n) 175 for i, v := range a[0:n] { 176 gids[i] = int(v) 177 } 178 return 179 } 180 181 func Setgroups(gids []int) (err error) { 182 if len(gids) == 0 { 183 return setgroups(0, nil) 184 } 185 186 a := make([]_Gid_t, len(gids)) 187 for i, v := range gids { 188 a[i] = _Gid_t(v) 189 } 190 return setgroups(len(a), &a[0]) 191 } 192 193 func ReadDirent(fd int, buf []byte) (n int, err error) { 194 // Final argument is (basep *uintptr) and the syscall doesn't take nil. 195 // TODO(rsc): Can we use a single global basep for all calls? 196 return Getdents(fd, buf, new(uintptr)) 197 } 198 199 // Wait status is 7 bits at bottom, either 0 (exited), 200 // 0x7F (stopped), or a signal number that caused an exit. 201 // The 0x80 bit is whether there was a core dump. 202 // An extra number (exit code, signal causing a stop) 203 // is in the high bits. 204 205 type WaitStatus uint32 206 207 const ( 208 mask = 0x7F 209 core = 0x80 210 shift = 8 211 212 exited = 0 213 stopped = 0x7F 214 ) 215 216 func (w WaitStatus) Exited() bool { return w&mask == exited } 217 218 func (w WaitStatus) ExitStatus() int { 219 if w&mask != exited { 220 return -1 221 } 222 return int(w >> shift) 223 } 224 225 func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 } 226 227 func (w WaitStatus) Signal() Signal { 228 sig := Signal(w & mask) 229 if sig == stopped || sig == 0 { 230 return -1 231 } 232 return sig 233 } 234 235 func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } 236 237 func (w WaitStatus) Stopped() bool { return w&mask == stopped && Signal(w>>shift) != SIGSTOP } 238 239 func (w WaitStatus) Continued() bool { return w&mask == stopped && Signal(w>>shift) == SIGSTOP } 240 241 func (w WaitStatus) StopSignal() Signal { 242 if !w.Stopped() { 243 return -1 244 } 245 return Signal(w>>shift) & 0xFF 246 } 247 248 func (w WaitStatus) TrapCause() int { return -1 } 249 250 func wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid uintptr, err uintptr) 251 252 func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { 253 r0, e1 := wait4(uintptr(pid), wstatus, uintptr(options), rusage) 254 if e1 != 0 { 255 err = Errno(e1) 256 } 257 return int(r0), err 258 } 259 260 func gethostname() (name string, err uintptr) 261 262 func Gethostname() (name string, err error) { 263 name, e1 := gethostname() 264 if e1 != 0 { 265 err = Errno(e1) 266 } 267 return name, err 268 } 269 270 func UtimesNano(path string, ts []Timespec) (err error) { 271 if len(ts) != 2 { 272 return EINVAL 273 } 274 var tv [2]Timeval 275 for i := 0; i < 2; i++ { 276 tv[i].Sec = ts[i].Sec 277 tv[i].Usec = ts[i].Nsec / 1000 278 } 279 return Utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 280 } 281 282 //sys fcntl(fd int, cmd int, arg int) (val int, err error) 283 284 // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. 285 func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { 286 _, _, e1 := sysvicall6(procfcntl.Addr(), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0) 287 if e1 != 0 { 288 return e1 289 } 290 return nil 291 } 292 293 func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { 294 switch rsa.Addr.Family { 295 case AF_UNIX: 296 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 297 sa := new(SockaddrUnix) 298 // Assume path ends at NUL. 299 // This is not technically the Solaris semantics for 300 // abstract Unix domain sockets -- they are supposed 301 // to be uninterpreted fixed-size binary blobs -- but 302 // everyone uses this convention. 303 n := 0 304 for n < len(pp.Path) && pp.Path[n] != 0 { 305 n++ 306 } 307 bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] 308 sa.Name = string(bytes) 309 return sa, nil 310 311 case AF_INET: 312 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 313 sa := new(SockaddrInet4) 314 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 315 sa.Port = int(p[0])<<8 + int(p[1]) 316 for i := 0; i < len(sa.Addr); i++ { 317 sa.Addr[i] = pp.Addr[i] 318 } 319 return sa, nil 320 321 case AF_INET6: 322 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 323 sa := new(SockaddrInet6) 324 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 325 sa.Port = int(p[0])<<8 + int(p[1]) 326 sa.ZoneId = pp.Scope_id 327 for i := 0; i < len(sa.Addr); i++ { 328 sa.Addr[i] = pp.Addr[i] 329 } 330 return sa, nil 331 } 332 return nil, EAFNOSUPPORT 333 } 334 335 //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept 336 337 func Accept(fd int) (nfd int, sa Sockaddr, err error) { 338 var rsa RawSockaddrAny 339 var len _Socklen = SizeofSockaddrAny 340 nfd, err = accept(fd, &rsa, &len) 341 if err != nil { 342 return 343 } 344 sa, err = anyToSockaddr(&rsa) 345 if err != nil { 346 Close(nfd) 347 nfd = 0 348 } 349 return 350 } 351 352 func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { 353 var msg Msghdr 354 var rsa RawSockaddrAny 355 msg.Name = (*byte)(unsafe.Pointer(&rsa)) 356 msg.Namelen = uint32(SizeofSockaddrAny) 357 var iov Iovec 358 if len(p) > 0 { 359 iov.Base = (*int8)(unsafe.Pointer(&p[0])) 360 iov.SetLen(len(p)) 361 } 362 var dummy int8 363 if len(oob) > 0 { 364 // receive at least one normal byte 365 if len(p) == 0 { 366 iov.Base = &dummy 367 iov.SetLen(1) 368 } 369 msg.Accrights = (*int8)(unsafe.Pointer(&oob[0])) 370 } 371 msg.Iov = &iov 372 msg.Iovlen = 1 373 if n, err = recvmsg(fd, &msg, flags); err != nil { 374 return 375 } 376 oobn = int(msg.Accrightslen) 377 // source address is only specified if the socket is unconnected 378 if rsa.Addr.Family != AF_UNSPEC { 379 from, err = anyToSockaddr(&rsa) 380 } 381 return 382 } 383 384 func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { 385 _, err = SendmsgN(fd, p, oob, to, flags) 386 return 387 } 388 389 //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.sendmsg 390 391 func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { 392 var ptr unsafe.Pointer 393 var salen _Socklen 394 if to != nil { 395 ptr, salen, err = to.sockaddr() 396 if err != nil { 397 return 0, err 398 } 399 } 400 var msg Msghdr 401 msg.Name = (*byte)(unsafe.Pointer(ptr)) 402 msg.Namelen = uint32(salen) 403 var iov Iovec 404 if len(p) > 0 { 405 iov.Base = (*int8)(unsafe.Pointer(&p[0])) 406 iov.SetLen(len(p)) 407 } 408 var dummy int8 409 if len(oob) > 0 { 410 // send at least one normal byte 411 if len(p) == 0 { 412 iov.Base = &dummy 413 iov.SetLen(1) 414 } 415 msg.Accrights = (*int8)(unsafe.Pointer(&oob[0])) 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 Exit(code int) 440 //sys Fchdir(fd int) (err error) 441 //sys Fchmod(fd int, mode uint32) (err error) 442 //sys Fchown(fd int, uid int, gid int) (err error) 443 //sys Fpathconf(fd int, name int) (val int, err error) 444 //sys Fstat(fd int, stat *Stat_t) (err error) 445 //sys Getdents(fd int, buf []byte, basep *uintptr) (n int, err error) 446 //sysnb Getgid() (gid int) 447 //sysnb Getpid() (pid int) 448 //sys Geteuid() (euid int) 449 //sys Getegid() (egid int) 450 //sys Getppid() (ppid int) 451 //sys Getpriority(which int, who int) (n int, err error) 452 //sysnb Getrlimit(which int, lim *Rlimit) (err error) 453 //sysnb Gettimeofday(tv *Timeval) (err error) 454 //sysnb Getuid() (uid int) 455 //sys Kill(pid int, signum Signal) (err error) 456 //sys Lchown(path string, uid int, gid int) (err error) 457 //sys Link(path string, link string) (err error) 458 //sys Listen(s int, backlog int) (err error) = libsocket.listen 459 //sys Lstat(path string, stat *Stat_t) (err error) 460 //sys Mkdir(path string, mode uint32) (err error) 461 //sys Mknod(path string, mode uint32, dev int) (err error) 462 //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) 463 //sys Open(path string, mode int, perm uint32) (fd int, err error) 464 //sys Pathconf(path string, name int) (val int, err error) 465 //sys Pread(fd int, p []byte, offset int64) (n int, err error) 466 //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) 467 //sys read(fd int, p []byte) (n int, err error) 468 //sys Readlink(path string, buf []byte) (n int, err error) 469 //sys Rename(from string, to string) (err error) 470 //sys Rmdir(path string) (err error) 471 //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek 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.bind 493 //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.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.sendto 497 //sys socket(domain int, typ int, proto int) (fd int, err error) = libsocket.socket 498 //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.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.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.recvmsg 506 507 func readlen(fd int, buf *byte, nbuf int) (n int, err error) { 508 r0, _, e1 := sysvicall6(procread.Addr(), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) 509 n = int(r0) 510 if e1 != 0 { 511 err = e1 512 } 513 return 514 } 515 516 func writelen(fd int, buf *byte, nbuf int) (n int, err error) { 517 r0, _, e1 := sysvicall6(procwrite.Addr(), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) 518 n = int(r0) 519 if e1 != 0 { 520 err = e1 521 } 522 return 523 }