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 13package syscall 14 15import "unsafe" 16 17const _F_DUP2FD_CLOEXEC = F_DUP2FD_CLOEXEC 18 19func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 20func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 21func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 22func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 23 24// Implemented in asm_solaris_amd64.s. 25func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 26func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 27 28type SockaddrDatalink struct { 29 Family uint16 30 Index uint16 31 Type uint8 32 Nlen uint8 33 Alen uint8 34 Slen uint8 35 Data [244]int8 36 raw RawSockaddrDatalink 37} 38 39func direntIno(buf []byte) (uint64, bool) { 40 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) 41} 42 43func direntReclen(buf []byte) (uint64, bool) { 44 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) 45} 46 47func direntNamlen(buf []byte) (uint64, bool) { 48 reclen, ok := direntReclen(buf) 49 if !ok { 50 return 0, false 51 } 52 return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true 53} 54 55func Pipe(p []int) (err error) { 56 return Pipe2(p, 0) 57} 58 59//sysnb pipe2(p *[2]_C_int, flags int) (err error) 60 61func Pipe2(p []int, flags int) error { 62 if len(p) != 2 { 63 return EINVAL 64 } 65 var pp [2]_C_int 66 err := pipe2(&pp, flags) 67 if err == nil { 68 p[0] = int(pp[0]) 69 p[1] = int(pp[1]) 70 } 71 return err 72} 73 74//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = libsocket.accept4 75 76func Accept4(fd int, flags int) (int, Sockaddr, error) { 77 var rsa RawSockaddrAny 78 var addrlen _Socklen = SizeofSockaddrAny 79 nfd, err := accept4(fd, &rsa, &addrlen, flags) 80 if err != nil { 81 return 0, nil, err 82 } 83 if addrlen > SizeofSockaddrAny { 84 panic("RawSockaddrAny too small") 85 } 86 sa, err := anyToSockaddr(&rsa) 87 if err != nil { 88 Close(nfd) 89 return 0, nil, err 90 } 91 return nfd, sa, nil 92} 93 94func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { 95 if sa.Port < 0 || sa.Port > 0xFFFF { 96 return nil, 0, EINVAL 97 } 98 sa.raw.Family = AF_INET 99 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 100 p[0] = byte(sa.Port >> 8) 101 p[1] = byte(sa.Port) 102 sa.raw.Addr = sa.Addr 103 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil 104} 105 106func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { 107 if sa.Port < 0 || sa.Port > 0xFFFF { 108 return nil, 0, EINVAL 109 } 110 sa.raw.Family = AF_INET6 111 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 112 p[0] = byte(sa.Port >> 8) 113 p[1] = byte(sa.Port) 114 sa.raw.Scope_id = sa.ZoneId 115 sa.raw.Addr = sa.Addr 116 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil 117} 118 119func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { 120 name := sa.Name 121 n := len(name) 122 if n >= len(sa.raw.Path) { 123 return nil, 0, EINVAL 124 } 125 sa.raw.Family = AF_UNIX 126 for i := 0; i < n; i++ { 127 sa.raw.Path[i] = int8(name[i]) 128 } 129 // length is family (uint16), name, NUL. 130 sl := _Socklen(2) 131 if n > 0 { 132 sl += _Socklen(n) + 1 133 } 134 if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { 135 // Check sl > 3 so we don't change unnamed socket behavior. 136 sa.raw.Path[0] = 0 137 // Don't count trailing NUL for abstract address. 138 sl-- 139 } 140 141 return unsafe.Pointer(&sa.raw), sl, nil 142} 143 144func Getsockname(fd int) (sa Sockaddr, err error) { 145 var rsa RawSockaddrAny 146 var len _Socklen = SizeofSockaddrAny 147 if err = getsockname(fd, &rsa, &len); err != nil { 148 return 149 } 150 return anyToSockaddr(&rsa) 151} 152 153const ImplementsGetwd = true 154 155//sys Getcwd(buf []byte) (n int, err error) 156 157func Getwd() (wd string, err error) { 158 var buf [PathMax]byte 159 // Getcwd will return an error if it failed for any reason. 160 _, err = Getcwd(buf[0:]) 161 if err != nil { 162 return "", err 163 } 164 n := clen(buf[:]) 165 if n < 1 { 166 return "", EINVAL 167 } 168 return string(buf[:n]), nil 169} 170 171/* 172 * Wrapped 173 */ 174 175//sysnb getgroups(ngid int, gid *_Gid_t) (n int, err error) 176//sysnb setgroups(ngid int, gid *_Gid_t) (err error) 177 178func Getgroups() (gids []int, err error) { 179 n, err := getgroups(0, nil) 180 if err != nil { 181 return nil, err 182 } 183 if n == 0 { 184 return nil, nil 185 } 186 187 // Sanity check group count. Max is 16 on BSD. 188 if n < 0 || n > 1000 { 189 return nil, EINVAL 190 } 191 192 a := make([]_Gid_t, n) 193 n, err = getgroups(n, &a[0]) 194 if err != nil { 195 return nil, err 196 } 197 gids = make([]int, n) 198 for i, v := range a[0:n] { 199 gids[i] = int(v) 200 } 201 return 202} 203 204func Setgroups(gids []int) (err error) { 205 if len(gids) == 0 { 206 return setgroups(0, nil) 207 } 208 209 a := make([]_Gid_t, len(gids)) 210 for i, v := range gids { 211 a[i] = _Gid_t(v) 212 } 213 return setgroups(len(a), &a[0]) 214} 215 216func ReadDirent(fd int, buf []byte) (n int, err error) { 217 // Final argument is (basep *uintptr) and the syscall doesn't take nil. 218 // TODO(rsc): Can we use a single global basep for all calls? 219 return Getdents(fd, buf, new(uintptr)) 220} 221 222// Wait status is 7 bits at bottom, either 0 (exited), 223// 0x7F (stopped), or a signal number that caused an exit. 224// The 0x80 bit is whether there was a core dump. 225// An extra number (exit code, signal causing a stop) 226// is in the high bits. 227 228type WaitStatus uint32 229 230const ( 231 mask = 0x7F 232 core = 0x80 233 shift = 8 234 235 exited = 0 236 stopped = 0x7F 237) 238 239func (w WaitStatus) Exited() bool { return w&mask == exited } 240 241func (w WaitStatus) ExitStatus() int { 242 if w&mask != exited { 243 return -1 244 } 245 return int(w >> shift) 246} 247 248func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 } 249 250func (w WaitStatus) Signal() Signal { 251 sig := Signal(w & mask) 252 if sig == stopped || sig == 0 { 253 return -1 254 } 255 return sig 256} 257 258func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } 259 260func (w WaitStatus) Stopped() bool { return w&mask == stopped && Signal(w>>shift) != SIGSTOP } 261 262func (w WaitStatus) Continued() bool { return w&mask == stopped && Signal(w>>shift) == SIGSTOP } 263 264func (w WaitStatus) StopSignal() Signal { 265 if !w.Stopped() { 266 return -1 267 } 268 return Signal(w>>shift) & 0xFF 269} 270 271func (w WaitStatus) TrapCause() int { return -1 } 272 273func wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid uintptr, err uintptr) 274 275func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { 276 r0, e1 := wait4(uintptr(pid), wstatus, uintptr(options), rusage) 277 if e1 != 0 { 278 err = Errno(e1) 279 } 280 return int(r0), err 281} 282 283func gethostname() (name string, err uintptr) 284 285func Gethostname() (name string, err error) { 286 name, e1 := gethostname() 287 if e1 != 0 { 288 err = Errno(e1) 289 } 290 return name, err 291} 292 293func UtimesNano(path string, ts []Timespec) error { 294 if len(ts) != 2 { 295 return EINVAL 296 } 297 return utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) 298} 299 300//sys fcntl(fd int, cmd int, arg int) (val int, err error) 301 302// FcntlFlock performs a fcntl syscall for the [F_GETLK], [F_SETLK] or [F_SETLKW] command. 303func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { 304 _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_fcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0) 305 if e1 != 0 { 306 return e1 307 } 308 return nil 309} 310 311func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { 312 switch rsa.Addr.Family { 313 case AF_UNIX: 314 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 315 sa := new(SockaddrUnix) 316 // Assume path ends at NUL. 317 // This is not technically the Solaris semantics for 318 // abstract Unix domain sockets -- they are supposed 319 // to be uninterpreted fixed-size binary blobs -- but 320 // everyone uses this convention. 321 n := 0 322 for n < len(pp.Path) && pp.Path[n] != 0 { 323 n++ 324 } 325 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) 326 return sa, nil 327 328 case AF_INET: 329 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 330 sa := new(SockaddrInet4) 331 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 332 sa.Port = int(p[0])<<8 + int(p[1]) 333 sa.Addr = pp.Addr 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 sa.Addr = pp.Addr 343 return sa, nil 344 } 345 return nil, EAFNOSUPPORT 346} 347 348//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept 349 350func Accept(fd int) (nfd int, sa Sockaddr, err error) { 351 var rsa RawSockaddrAny 352 var len _Socklen = SizeofSockaddrAny 353 nfd, err = accept(fd, &rsa, &len) 354 if err != nil { 355 return 356 } 357 sa, err = anyToSockaddr(&rsa) 358 if err != nil { 359 Close(nfd) 360 nfd = 0 361 } 362 return 363} 364 365func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { 366 var msg Msghdr 367 msg.Name = (*byte)(unsafe.Pointer(rsa)) 368 msg.Namelen = uint32(SizeofSockaddrAny) 369 var iov Iovec 370 if len(p) > 0 { 371 iov.Base = (*int8)(unsafe.Pointer(&p[0])) 372 iov.SetLen(len(p)) 373 } 374 var dummy int8 375 if len(oob) > 0 { 376 // receive at least one normal byte 377 if len(p) == 0 { 378 iov.Base = &dummy 379 iov.SetLen(1) 380 } 381 msg.Accrights = (*int8)(unsafe.Pointer(&oob[0])) 382 msg.Accrightslen = int32(len(oob)) 383 } 384 msg.Iov = &iov 385 msg.Iovlen = 1 386 if n, err = recvmsg(fd, &msg, flags); err != nil { 387 return 388 } 389 oobn = int(msg.Accrightslen) 390 return 391} 392 393//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg 394 395func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { 396 var msg Msghdr 397 msg.Name = (*byte)(unsafe.Pointer(ptr)) 398 msg.Namelen = uint32(salen) 399 var iov Iovec 400 if len(p) > 0 { 401 iov.Base = (*int8)(unsafe.Pointer(&p[0])) 402 iov.SetLen(len(p)) 403 } 404 var dummy int8 405 if len(oob) > 0 { 406 // send at least one normal byte 407 if len(p) == 0 { 408 iov.Base = &dummy 409 iov.SetLen(1) 410 } 411 msg.Accrights = (*int8)(unsafe.Pointer(&oob[0])) 412 msg.Accrightslen = int32(len(oob)) 413 } 414 msg.Iov = &iov 415 msg.Iovlen = 1 416 if n, err = sendmsg(fd, &msg, flags); err != nil { 417 return 0, err 418 } 419 if len(oob) > 0 && len(p) == 0 { 420 n = 0 421 } 422 return n, nil 423} 424 425/* 426 * Exposed directly 427 */ 428//sys Access(path string, mode uint32) (err error) 429//sys Adjtime(delta *Timeval, olddelta *Timeval) (err error) 430//sys Chdir(path string) (err error) 431//sys Chmod(path string, mode uint32) (err error) 432//sys Chown(path string, uid int, gid int) (err error) 433//sys Chroot(path string) (err error) 434//sys Close(fd int) (err error) 435//sys Dup(fd int) (nfd int, err error) 436//sys Fchdir(fd int) (err error) 437//sys Fchmod(fd int, mode uint32) (err error) 438//sys Fchown(fd int, uid int, gid int) (err error) 439//sys Fpathconf(fd int, name int) (val int, err error) 440//sys Fstat(fd int, stat *Stat_t) (err error) 441//sys Getdents(fd int, buf []byte, basep *uintptr) (n int, err error) 442//sysnb Getgid() (gid int) 443//sysnb Getpid() (pid int) 444//sys Geteuid() (euid int) 445//sys Getegid() (egid int) 446//sys Getppid() (ppid int) 447//sys Getpriority(which int, who int) (n int, err error) 448//sysnb Getrlimit(which int, lim *Rlimit) (err error) 449//sysnb Getrusage(who int, rusage *Rusage) (err error) 450//sysnb Gettimeofday(tv *Timeval) (err error) 451//sysnb Getuid() (uid int) 452//sys Kill(pid int, signum Signal) (err error) 453//sys Lchown(path string, uid int, gid int) (err error) 454//sys Link(path string, link string) (err error) 455//sys Listen(s int, backlog int) (err error) = libsocket.__xnet_listen 456//sys Lstat(path string, stat *Stat_t) (err error) 457//sys Mkdir(path string, mode uint32) (err error) 458//sys Mknod(path string, mode uint32, dev int) (err error) 459//sys Nanosleep(time *Timespec, leftover *Timespec) (err error) 460//sys Open(path string, mode int, perm uint32) (fd int, err error) 461//sys Pathconf(path string, name int) (val int, err error) 462//sys pread(fd int, p []byte, offset int64) (n int, err error) 463//sys pwrite(fd int, p []byte, offset int64) (n int, err error) 464//sys read(fd int, p []byte) (n int, err error) 465//sys Readlink(path string, buf []byte) (n int, err error) 466//sys Rename(from string, to string) (err error) 467//sys Rmdir(path string) (err error) 468//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek 469//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile 470//sysnb Setegid(egid int) (err error) 471//sysnb Seteuid(euid int) (err error) 472//sysnb Setgid(gid int) (err error) 473//sysnb Setpgid(pid int, pgid int) (err error) 474//sys Setpriority(which int, who int, prio int) (err error) 475//sysnb Setregid(rgid int, egid int) (err error) 476//sysnb Setreuid(ruid int, euid int) (err error) 477//sysnb setrlimit(which int, lim *Rlimit) (err error) 478//sysnb Setsid() (pid int, err error) 479//sysnb Setuid(uid int) (err error) 480//sys Shutdown(s int, how int) (err error) = libsocket.shutdown 481//sys Stat(path string, stat *Stat_t) (err error) 482//sys Symlink(path string, link string) (err error) 483//sys Sync() (err error) 484//sys Truncate(path string, length int64) (err error) 485//sys Fsync(fd int) (err error) 486//sys Ftruncate(fd int, length int64) (err error) 487//sys Umask(newmask int) (oldmask int) 488//sys Unlink(path string) (err error) 489//sys utimes(path string, times *[2]Timeval) (err error) 490//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind 491//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect 492//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) 493//sys munmap(addr uintptr, length uintptr) (err error) 494//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto 495//sys socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket 496//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair 497//sys write(fd int, p []byte) (n int, err error) 498//sys writev(fd int, iovecs []Iovec) (n uintptr, err error) 499//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt 500//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername 501//sys getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname 502//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt 503//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom 504//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg 505//sys getexecname() (path unsafe.Pointer, err error) = libc.getexecname 506//sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error) 507 508func Getexecname() (path string, err error) { 509 ptr, err := getexecname() 510 if err != nil { 511 return "", err 512 } 513 bytes := (*[1 << 29]byte)(ptr)[:] 514 for i, b := range bytes { 515 if b == 0 { 516 return string(bytes[:i]), nil 517 } 518 } 519 panic("unreachable") 520} 521 522func readlen(fd int, buf *byte, nbuf int) (n int, err error) { 523 r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_read)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) 524 n = int(r0) 525 if e1 != 0 { 526 err = e1 527 } 528 return 529} 530 531var mapper = &mmapper{ 532 active: make(map[*byte][]byte), 533 mmap: mmap, 534 munmap: munmap, 535} 536 537func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 538 return mapper.Mmap(fd, offset, length, prot, flags) 539} 540 541func Munmap(b []byte) (err error) { 542 return mapper.Munmap(b) 543} 544 545func Utimes(path string, tv []Timeval) error { 546 if len(tv) != 2 { 547 return EINVAL 548 } 549 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 550} 551