]> Cypherpunks.ru repositories - gostls13.git/blob - src/syscall/syscall_darwin.go
syscall: provide and use ioctlPtr for all BSD platforms
[gostls13.git] / src / syscall / syscall_darwin.go
1 // Copyright 2009,2010 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 // Darwin 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_bsd.go or syscall_unix.go.
12
13 package syscall
14
15 import (
16         "internal/abi"
17         "unsafe"
18 )
19
20 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
21 func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
22 func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
23 func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
24
25 var dupTrampoline = abi.FuncPCABI0(libc_dup2_trampoline)
26
27 type SockaddrDatalink struct {
28         Len    uint8
29         Family uint8
30         Index  uint16
31         Type   uint8
32         Nlen   uint8
33         Alen   uint8
34         Slen   uint8
35         Data   [12]int8
36         raw    RawSockaddrDatalink
37 }
38
39 // Translate "kern.hostname" to []_C_int{0,1,2,3}.
40 func nametomib(name string) (mib []_C_int, err error) {
41         const siz = unsafe.Sizeof(mib[0])
42
43         // NOTE(rsc): It seems strange to set the buffer to have
44         // size CTL_MAXNAME+2 but use only CTL_MAXNAME
45         // as the size. I don't know why the +2 is here, but the
46         // kernel uses +2 for its own implementation of this function.
47         // I am scared that if we don't include the +2 here, the kernel
48         // will silently write 2 words farther than we specify
49         // and we'll get memory corruption.
50         var buf [CTL_MAXNAME + 2]_C_int
51         n := uintptr(CTL_MAXNAME) * siz
52
53         p := (*byte)(unsafe.Pointer(&buf[0]))
54         bytes, err := ByteSliceFromString(name)
55         if err != nil {
56                 return nil, err
57         }
58
59         // Magic sysctl: "setting" 0.3 to a string name
60         // lets you read back the array of integers form.
61         if err = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); err != nil {
62                 return nil, err
63         }
64         return buf[0 : n/siz], nil
65 }
66
67 func direntIno(buf []byte) (uint64, bool) {
68         return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
69 }
70
71 func direntReclen(buf []byte) (uint64, bool) {
72         return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
73 }
74
75 func direntNamlen(buf []byte) (uint64, bool) {
76         return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
77 }
78
79 func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
80 func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
81
82 //sysnb pipe(p *[2]int32) (err error)
83
84 func Pipe(p []int) (err error) {
85         if len(p) != 2 {
86                 return EINVAL
87         }
88         var q [2]int32
89         err = pipe(&q)
90         if err == nil {
91                 p[0] = int(q[0])
92                 p[1] = int(q[1])
93         }
94         return
95 }
96
97 func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
98         var _p0 unsafe.Pointer
99         var bufsize uintptr
100         if len(buf) > 0 {
101                 _p0 = unsafe.Pointer(&buf[0])
102                 bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
103         }
104         r0, _, e1 := syscall(abi.FuncPCABI0(libc_getfsstat_trampoline), uintptr(_p0), bufsize, uintptr(flags))
105         n = int(r0)
106         if e1 != 0 {
107                 err = e1
108         }
109         return
110 }
111
112 func libc_getfsstat_trampoline()
113
114 //go:cgo_import_dynamic libc_getfsstat getfsstat "/usr/lib/libSystem.B.dylib"
115
116 //sys   utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)
117
118 /*
119  * Wrapped
120  */
121
122 //sys   kill(pid int, signum int, posix int) (err error)
123
124 func Kill(pid int, signum Signal) (err error) { return kill(pid, int(signum), 1) }
125
126 /*
127  * Exposed directly
128  */
129 //sys   Access(path string, mode uint32) (err error)
130 //sys   Adjtime(delta *Timeval, olddelta *Timeval) (err error)
131 //sys   Chdir(path string) (err error)
132 //sys   Chflags(path string, flags int) (err error)
133 //sys   Chmod(path string, mode uint32) (err error)
134 //sys   Chown(path string, uid int, gid int) (err error)
135 //sys   Chroot(path string) (err error)
136 //sys   Close(fd int) (err error)
137 //sys   closedir(dir uintptr) (err error)
138 //sys   Dup(fd int) (nfd int, err error)
139 //sys   Dup2(from int, to int) (err error)
140 //sys   Exchangedata(path1 string, path2 string, options int) (err error)
141 //sys   Fchdir(fd int) (err error)
142 //sys   Fchflags(fd int, flags int) (err error)
143 //sys   Fchmod(fd int, mode uint32) (err error)
144 //sys   Fchown(fd int, uid int, gid int) (err error)
145 //sys   Flock(fd int, how int) (err error)
146 //sys   Fpathconf(fd int, name int) (val int, err error)
147 //sys   Fsync(fd int) (err error)
148 //  Fsync is not called for os.File.Sync(). Please see internal/poll/fd_fsync_darwin.go
149 //sys   Ftruncate(fd int, length int64) (err error)
150 //sys   Getdtablesize() (size int)
151 //sysnb Getegid() (egid int)
152 //sysnb Geteuid() (uid int)
153 //sysnb Getgid() (gid int)
154 //sysnb Getpgid(pid int) (pgid int, err error)
155 //sysnb Getpgrp() (pgrp int)
156 //sysnb Getpid() (pid int)
157 //sysnb Getppid() (ppid int)
158 //sys   Getpriority(which int, who int) (prio int, err error)
159 //sysnb Getrlimit(which int, lim *Rlimit) (err error)
160 //sysnb Getrusage(who int, rusage *Rusage) (err error)
161 //sysnb Getsid(pid int) (sid int, err error)
162 //sysnb Getuid() (uid int)
163 //sysnb Issetugid() (tainted bool)
164 //sys   Kqueue() (fd int, err error)
165 //sys   Lchown(path string, uid int, gid int) (err error)
166 //sys   Link(path string, link string) (err error)
167 //sys   Listen(s int, backlog int) (err error)
168 //sys   Mkdir(path string, mode uint32) (err error)
169 //sys   Mkfifo(path string, mode uint32) (err error)
170 //sys   Mknod(path string, mode uint32, dev int) (err error)
171 //sys   Mlock(b []byte) (err error)
172 //sys   Mlockall(flags int) (err error)
173 //sys   Mprotect(b []byte, prot int) (err error)
174 //sys   msync(b []byte, flags int) (err error)
175 //sys   Munlock(b []byte) (err error)
176 //sys   Munlockall() (err error)
177 //sys   Open(path string, mode int, perm uint32) (fd int, err error)
178 //sys   Pathconf(path string, name int) (val int, err error)
179 //sys   pread(fd int, p []byte, offset int64) (n int, err error)
180 //sys   pwrite(fd int, p []byte, offset int64) (n int, err error)
181 //sys   read(fd int, p []byte) (n int, err error)
182 //sys   readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)
183 //sys   Readlink(path string, buf []byte) (n int, err error)
184 //sys   Rename(from string, to string) (err error)
185 //sys   Revoke(path string) (err error)
186 //sys   Rmdir(path string) (err error)
187 //sys   Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_lseek
188 //sys   Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
189 //sys   Setegid(egid int) (err error)
190 //sysnb Seteuid(euid int) (err error)
191 //sysnb Setgid(gid int) (err error)
192 //sys   Setlogin(name string) (err error)
193 //sysnb Setpgid(pid int, pgid int) (err error)
194 //sys   Setpriority(which int, who int, prio int) (err error)
195 //sys   Setprivexec(flag int) (err error)
196 //sysnb Setregid(rgid int, egid int) (err error)
197 //sysnb Setreuid(ruid int, euid int) (err error)
198 //sysnb setrlimit(which int, lim *Rlimit) (err error)
199 //sysnb Setsid() (pid int, err error)
200 //sysnb Settimeofday(tp *Timeval) (err error)
201 //sysnb Setuid(uid int) (err error)
202 //sys   Symlink(path string, link string) (err error)
203 //sys   Sync() (err error)
204 //sys   Truncate(path string, length int64) (err error)
205 //sys   Umask(newmask int) (oldmask int)
206 //sys   Undelete(path string) (err error)
207 //sys   Unlink(path string) (err error)
208 //sys   Unmount(path string, flags int) (err error)
209 //sys   write(fd int, p []byte) (n int, err error)
210 //sys   writev(fd int, iovecs []Iovec) (cnt uintptr, err error)
211 //sys   mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
212 //sys   munmap(addr uintptr, length uintptr) (err error)
213 //sysnb fork() (pid int, err error)
214 //sysnb execve(path *byte, argv **byte, envp **byte) (err error)
215 //sysnb exit(res int) (err error)
216 //sys   sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error)
217 //sys   unlinkat(fd int, path string, flags int) (err error)
218 //sys   openat(fd int, path string, flags int, perm uint32) (fdret int, err error)
219 //sys   getcwd(buf []byte) (n int, err error)
220
221 func init() {
222         execveDarwin = execve
223 }
224
225 func fdopendir(fd int) (dir uintptr, err error) {
226         r0, _, e1 := syscallPtr(abi.FuncPCABI0(libc_fdopendir_trampoline), uintptr(fd), 0, 0)
227         dir = r0
228         if e1 != 0 {
229                 err = errnoErr(e1)
230         }
231         return
232 }
233
234 func libc_fdopendir_trampoline()
235
236 //go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib"
237
238 func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
239         r0, _, e1 := syscall(abi.FuncPCABI0(libc_read_trampoline), uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
240         n = int(r0)
241         if e1 != 0 {
242                 err = errnoErr(e1)
243         }
244         return
245 }
246
247 func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
248         // Simulate Getdirentries using fdopendir/readdir_r/closedir.
249         // We store the number of entries to skip in the seek
250         // offset of fd. See issue #31368.
251         // It's not the full required semantics, but should handle the case
252         // of calling Getdirentries or ReadDirent repeatedly.
253         // It won't handle assigning the results of lseek to *basep, or handle
254         // the directory being edited underfoot.
255         skip, err := Seek(fd, 0, 1 /* SEEK_CUR */)
256         if err != nil {
257                 return 0, err
258         }
259
260         // We need to duplicate the incoming file descriptor
261         // because the caller expects to retain control of it, but
262         // fdopendir expects to take control of its argument.
263         // Just Dup'ing the file descriptor is not enough, as the
264         // result shares underlying state. Use openat to make a really
265         // new file descriptor referring to the same directory.
266         fd2, err := openat(fd, ".", O_RDONLY, 0)
267         if err != nil {
268                 return 0, err
269         }
270         d, err := fdopendir(fd2)
271         if err != nil {
272                 Close(fd2)
273                 return 0, err
274         }
275         defer closedir(d)
276
277         var cnt int64
278         for {
279                 var entry Dirent
280                 var entryp *Dirent
281                 e := readdir_r(d, &entry, &entryp)
282                 if e != 0 {
283                         return n, errnoErr(e)
284                 }
285                 if entryp == nil {
286                         break
287                 }
288                 if skip > 0 {
289                         skip--
290                         cnt++
291                         continue
292                 }
293                 reclen := int(entry.Reclen)
294                 if reclen > len(buf) {
295                         // Not enough room. Return for now.
296                         // The counter will let us know where we should start up again.
297                         // Note: this strategy for suspending in the middle and
298                         // restarting is O(n^2) in the length of the directory. Oh well.
299                         break
300                 }
301                 // Copy entry into return buffer.
302                 copy(buf, unsafe.Slice((*byte)(unsafe.Pointer(&entry)), reclen))
303                 buf = buf[reclen:]
304                 n += reclen
305                 cnt++
306         }
307         // Set the seek offset of the input fd to record
308         // how many files we've already returned.
309         _, err = Seek(fd, cnt, 0 /* SEEK_SET */)
310         if err != nil {
311                 return n, err
312         }
313
314         return n, nil
315 }
316
317 // Implemented in the runtime package (runtime/sys_darwin.go)
318 func syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
319 func syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
320 func syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
321 func rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
322 func rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
323 func syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)