OSDN Git Service

f5358f53d9b64473ac3ca7a93fe5095d3c4cccac
[pf3gnuchains/gcc-fork.git] / libgo / go / syscall / libcall_linux.go
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 // GNU/Linux library calls.
6
7 package syscall
8
9 import "unsafe"
10
11 //sys   Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
12 //openat(dirfd int, path *byte, flags int, mode Mode_t) int
13
14 //sys   futimesat(dirfd int, path *byte, times *[2]Timeval) (err error)
15 //futimesat(dirfd int, path *byte, times *[2]Timeval) int
16 func Futimesat(dirfd int, path string, tv []Timeval) (err error) {
17         if len(tv) != 2 {
18                 return EINVAL
19         }
20         return futimesat(dirfd, StringBytePtr(path), (*[2]Timeval)(unsafe.Pointer(&tv[0])))
21 }
22
23 func Futimes(fd int, tv []Timeval) (err error) {
24         // Believe it or not, this is the best we can do on GNU/Linux
25         // (and is what glibc does).
26         return Utimes("/proc/self/fd/"+itoa(fd), tv)
27 }
28
29 //sys   ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
30 //ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
31
32 //sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno)
33 //ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
34
35 func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) {
36         // The peek requests are machine-size oriented, so we wrap it
37         // to retrieve arbitrary-length data.
38
39         // The ptrace syscall differs from glibc's ptrace.
40         // Peeks returns the word in *data, not as the return value.
41
42         var buf [sizeofPtr]byte
43
44         // Leading edge.  PEEKTEXT/PEEKDATA don't require aligned
45         // access (PEEKUSER warns that it might), but if we don't
46         // align our reads, we might straddle an unmapped page
47         // boundary and not get the bytes leading up to the page
48         // boundary.
49         n := 0
50         if addr%sizeofPtr != 0 {
51                 err = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
52                 if err != nil {
53                         return 0, err
54                 }
55                 n += copy(out, buf[addr%sizeofPtr:])
56                 out = out[n:]
57         }
58
59         // Remainder.
60         for len(out) > 0 {
61                 // We use an internal buffer to gaurantee alignment.
62                 // It's not documented if this is necessary, but we're paranoid.
63                 err = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
64                 if err != nil {
65                         return n, err
66                 }
67                 copied := copy(out, buf[0:])
68                 n += copied
69                 out = out[copied:]
70         }
71
72         return n, nil
73 }
74
75 func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) {
76         return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out)
77 }
78
79 func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
80         return ptracePeek(PTRACE_PEEKDATA, pid, addr, out)
81 }
82
83 func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, err error) {
84         // As for ptracePeek, we need to align our accesses to deal
85         // with the possibility of straddling an invalid page.
86
87         // Leading edge.
88         n := 0
89         if addr%sizeofPtr != 0 {
90                 var buf [sizeofPtr]byte
91                 err = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
92                 if err != nil {
93                         return 0, err
94                 }
95                 n += copy(buf[addr%sizeofPtr:], data)
96                 word := *((*uintptr)(unsafe.Pointer(&buf[0])))
97                 err = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
98                 if err != nil {
99                         return 0, err
100                 }
101                 data = data[n:]
102         }
103
104         // Interior.
105         for len(data) > int(sizeofPtr) {
106                 word := *((*uintptr)(unsafe.Pointer(&data[0])))
107                 err = ptrace(pokeReq, pid, addr+uintptr(n), word)
108                 if err != nil {
109                         return n, err
110                 }
111                 n += int(sizeofPtr)
112                 data = data[sizeofPtr:]
113         }
114
115         // Trailing edge.
116         if len(data) > 0 {
117                 var buf [sizeofPtr]byte
118                 err = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
119                 if err != nil {
120                         return n, err
121                 }
122                 copy(buf[0:], data)
123                 word := *((*uintptr)(unsafe.Pointer(&buf[0])))
124                 err = ptrace(pokeReq, pid, addr+uintptr(n), word)
125                 if err != nil {
126                         return n, err
127                 }
128                 n += len(data)
129         }
130
131         return n, nil
132 }
133
134 func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
135         return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data)
136 }
137
138 func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
139         return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data)
140 }
141
142 func PtraceSetOptions(pid int, options int) (err error) {
143         return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options))
144 }
145
146 func PtraceGetEventMsg(pid int) (msg uint, err error) {
147         var data _C_long
148         err = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)))
149         msg = uint(data)
150         return
151 }
152
153 func PtraceCont(pid int, signal int) (err error) {
154         return ptrace(PTRACE_CONT, pid, 0, uintptr(signal))
155 }
156
157 func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
158
159 func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
160
161 func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
162
163 //sys   reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error)
164 //reboot(magic1 uint, magic2 uint, cmd int, arg *byte) int
165 func Reboot(cmd int) (err error) {
166         return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
167 }
168
169 //sys   Acct(path string) (err error)
170 //acct(path *byte) int
171
172 //sys   Adjtimex(buf *Timex) (state int, err error)
173 //adjtimex(buf *Timex) int
174
175 //sys   Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
176 //faccessat(dirfd int, pathname *byte, mode int, flags int) int
177
178 //sys   Fallocate(fd int, mode uint32, off int64, len int64) (err error)
179 //fallocate(fd int, mode int, offset Offset_t, len Offset_t) int
180
181 //sys   Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
182 //fchmodat(dirfd int, pathname *byte, mode Mode_t, flags int) int
183
184 //sys   Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
185 //fchownat(dirfd int, path *byte, owner Uid_t, group Gid_t, flags int) int
186
187 //sys   Flock(fd int, how int) (err error)
188 //flock(fd int, how int) int
189
190 //sys   Fstatfs(fd int, buf *Statfs_t) (err error)
191 //fstatfs(fd int, buf *Statfs_t) int
192
193 func Gettid() (tid int) {
194         r1, _, _ := Syscall(SYS_GETTID, 0, 0, 0)
195         return int(r1)
196 }
197
198 func Getdents(fd int, buf []byte) (n int, err error) {
199         var p *byte
200         if len(buf) > 0 {
201                 p = &buf[0]
202         } else {
203                 p = (*byte)(unsafe.Pointer(&_zero))
204         }
205         Entersyscall()
206         r1, _, errno := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(len(buf)))
207         n = int(r1)
208         if n < 0 {
209                 err = errno
210         }
211         Exitsyscall()
212         return
213 }
214
215 func clen(n []byte) int {
216         for i := 0; i < len(n); i++ {
217                 if n[i] == 0 {
218                         return i
219                 }
220         }
221         return len(n)
222 }
223
224 func ReadDirent(fd int, buf []byte) (n int, err error) {
225         return Getdents(fd, buf)
226 }
227
228 func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
229         origlen := len(buf)
230         count = 0
231         for max != 0 && len(buf) > 0 {
232                 dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
233                 buf = buf[dirent.Reclen:]
234                 if dirent.Ino == 0 { // File absent in directory.
235                         continue
236                 }
237                 bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
238                 var name = string(bytes[0:clen(bytes[:])])
239                 if name == "." || name == ".." { // Useless names
240                         continue
241                 }
242                 max--
243                 count++
244                 names = append(names, name)
245         }
246         return origlen - len(buf), count, names
247 }
248
249 //sys   InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error)
250 //inotify_add_watch(fd int, pathname *byte, mask uint32) int
251
252 //sysnb InotifyInit() (fd int, err error)
253 //inotify_init() int
254
255 //sysnb InotifyInit1(flags int) (fd int, err error)
256 //inotify_init1(flags int) int
257
258 //sysnb InotifyRmWatch(fd int, watchdesc uint32) (success int, err error)
259 //inotify_rm_watch(fd int, wd uint32) int
260
261 //sys   Klogctl(typ int, buf []byte) (n int, err error)
262 //klogctl(typ int, bufp *byte, len int) int
263
264 //sys   Mkdirat(dirfd int, path string, mode uint32) (err error)
265 //mkdirat(dirfd int, path *byte, mode Mode_t) int
266
267 //sys   Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
268 //mknodat(dirfd int, path *byte, mode Mode_t, dev _dev_t) int
269
270 //sys   PivotRoot(newroot string, putold string) (err error)
271 //pivot_root(newroot *byte, putold *byte) int
272
273 //sys   Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
274 //renameat(olddirfd int, oldpath *byte, newdirfd int, newpath *byte) int
275
276 //sys   sendfile(outfd int, infd int, offset *Offset_t, count int) (written int, err error)
277 //sendfile64(outfd int, infd int, offset *Offset_t, count Size_t) Ssize_t
278 func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
279         var soff Offset_t
280         var psoff *Offset_t
281         if offset != nil {
282                 psoff = &soff
283         }
284         written, err = sendfile(outfd, infd, psoff, count)
285         if offset != nil {
286                 *offset = int64(soff)
287         }
288         return
289 }
290
291 //sys   Setfsgid(gid int) (err error)
292 //setfsgid(gid Gid_t) int
293
294 //sys   Setfsuid(uid int) (err error)
295 //setfsuid(uid Uid_t) int
296
297 //sysnb Setresgid(rgid int, egid int, sgid int) (err error)
298 //setresgid(rgid Gid_t, egid Gid_t, sgid Gid_t) int
299
300 //sysnb Setresuid(ruid int, eguid int, suid int) (err error)
301 //setresuid(ruid Uid_t, euid Uid_t, suid Uid_t) int
302
303 //sys   splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, err error)
304 //splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len Size_t, flags uint) Ssize_t
305 func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
306         var lroff _loff_t
307         var plroff *_loff_t
308         if roff != nil {
309                 plroff = &lroff
310         }
311         var lwoff _loff_t
312         var plwoff *_loff_t
313         if woff != nil {
314                 plwoff = &lwoff
315         }
316         n, err = splice(rfd, plroff, wfd, plwoff, len, flags)
317         if roff != nil {
318                 *roff = int64(lroff)
319         }
320         if woff != nil {
321                 *woff = int64(lwoff)
322         }
323         return
324 }
325
326 //sys   Statfs(path string, buf *Statfs_t) (err error)
327 //statfs(path *byte, buf *Statfs_t) int
328
329 //sys   SyncFileRange(fd int, off int64, n int64, flags int) (err error)
330 //sync_file_range(fd int, off Offset_t, n Offset_t, flags uint) int
331
332 //sysnb Sysinfo(info *Sysinfo_t) (err error)
333 //sysinfo(info *Sysinfo_t) int
334
335 //sys   Tee(rfd int, wfd int, len int, flags int) (n int64, err error)
336 //tee(rfd int, wfd int, len Size_t, flags uint) Ssize_t
337
338 func Tgkill(tgid, tid, sig Signal) error {
339         r1, _, errno := Syscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
340         if r1 < 0 {
341                 return errno
342         }
343         return nil
344 }
345
346 //sys   unlinkat(dirfd int, path string, flags int) (err error)
347 //unlinkat(dirfd int, path *byte, flags int) int
348
349 func Unlinkat(dirfd int, path string) (err error) {
350         return unlinkat(dirfd, path, 0)
351 }
352
353 //sys   Unmount(target string, flags int) (err error) = SYS_UMOUNT2
354 //umount2(target *byte, flags int) int
355
356 //sys   Unshare(flags int) (err error)
357 //unshare(flags int) int
358
359 //sys   Ustat(dev int, ubuf *Ustat_t) (err error)
360 //ustat(dev _dev_t, ubuf *Ustat_t) int