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