syscall_solaris.mx raw
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 const _F_DUP2FD_CLOEXEC = F_DUP2FD_CLOEXEC
18
19 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
20 func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
21 func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
22 func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
23
24 // Implemented in asm_solaris_amd64.s.
25 func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
26 func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
27
28 type 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
39 func direntIno(buf []byte) (uint64, bool) {
40 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
41 }
42
43 func direntReclen(buf []byte) (uint64, bool) {
44 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
45 }
46
47 func 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
55 func Pipe(p []int) (err error) {
56 return Pipe2(p, 0)
57 }
58
59 //sysnb pipe2(p *[2]_C_int, flags int) (err error)
60
61 func 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
76 func 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
94 func (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
106 func (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
119 func (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
144 func 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
153 const ImplementsGetwd = true
154
155 //sys Getcwd(buf []byte) (n int, err error)
156
157 func 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
178 func 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
204 func 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
216 func 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
228 type WaitStatus uint32
229
230 const (
231 mask = 0x7F
232 core = 0x80
233 shift = 8
234
235 exited = 0
236 stopped = 0x7F
237 )
238
239 func (w WaitStatus) Exited() bool { return w&mask == exited }
240
241 func (w WaitStatus) ExitStatus() int {
242 if w&mask != exited {
243 return -1
244 }
245 return int(w >> shift)
246 }
247
248 func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
249
250 func (w WaitStatus) Signal() Signal {
251 sig := Signal(w & mask)
252 if sig == stopped || sig == 0 {
253 return -1
254 }
255 return sig
256 }
257
258 func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
259
260 func (w WaitStatus) Stopped() bool { return w&mask == stopped && Signal(w>>shift) != SIGSTOP }
261
262 func (w WaitStatus) Continued() bool { return w&mask == stopped && Signal(w>>shift) == SIGSTOP }
263
264 func (w WaitStatus) StopSignal() Signal {
265 if !w.Stopped() {
266 return -1
267 }
268 return Signal(w>>shift) & 0xFF
269 }
270
271 func (w WaitStatus) TrapCause() int { return -1 }
272
273 func wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid uintptr, err uintptr)
274
275 func 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
283 func gethostname() (name string, err uintptr)
284
285 func Gethostname() (name string, err error) {
286 name, e1 := gethostname()
287 if e1 != 0 {
288 err = Errno(e1)
289 }
290 return name, err
291 }
292
293 func 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.
303 func 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
311 func 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
350 func 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
365 func 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
395 func 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
508 func 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
522 func 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
531 var mapper = &mmapper{
532 active: make(map[*byte][]byte),
533 mmap: mmap,
534 munmap: munmap,
535 }
536
537 func 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
541 func Munmap(b []byte) (err error) {
542 return mapper.Munmap(b)
543 }
544
545 func 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