]>
Commit | Line | Data |
---|---|---|
9b12e4fe JC |
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 | // Linux 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 | |
10 | // wrap it in our own nicer implementation. | |
11 | ||
12 | package unix | |
13 | ||
14 | import ( | |
15 | "syscall" | |
16 | "unsafe" | |
17 | ) | |
18 | ||
19 | /* | |
20 | * Wrapped | |
21 | */ | |
22 | ||
23 | func Access(path string, mode uint32) (err error) { | |
24 | return Faccessat(AT_FDCWD, path, mode, 0) | |
25 | } | |
26 | ||
27 | func Chmod(path string, mode uint32) (err error) { | |
28 | return Fchmodat(AT_FDCWD, path, mode, 0) | |
29 | } | |
30 | ||
31 | func Chown(path string, uid int, gid int) (err error) { | |
32 | return Fchownat(AT_FDCWD, path, uid, gid, 0) | |
33 | } | |
34 | ||
35 | func Creat(path string, mode uint32) (fd int, err error) { | |
36 | return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) | |
37 | } | |
38 | ||
39 | //sys linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) | |
40 | ||
41 | func Link(oldpath string, newpath string) (err error) { | |
42 | return linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0) | |
43 | } | |
44 | ||
45 | func Mkdir(path string, mode uint32) (err error) { | |
46 | return Mkdirat(AT_FDCWD, path, mode) | |
47 | } | |
48 | ||
49 | func Mknod(path string, mode uint32, dev int) (err error) { | |
50 | return Mknodat(AT_FDCWD, path, mode, dev) | |
51 | } | |
52 | ||
53 | func Open(path string, mode int, perm uint32) (fd int, err error) { | |
54 | return openat(AT_FDCWD, path, mode|O_LARGEFILE, perm) | |
55 | } | |
56 | ||
57 | //sys openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) | |
58 | ||
59 | func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { | |
60 | return openat(dirfd, path, flags|O_LARGEFILE, mode) | |
61 | } | |
62 | ||
63 | //sys readlinkat(dirfd int, path string, buf []byte) (n int, err error) | |
64 | ||
65 | func Readlink(path string, buf []byte) (n int, err error) { | |
66 | return readlinkat(AT_FDCWD, path, buf) | |
67 | } | |
68 | ||
69 | func Rename(oldpath string, newpath string) (err error) { | |
70 | return Renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath) | |
71 | } | |
72 | ||
73 | func Rmdir(path string) error { | |
74 | return unlinkat(AT_FDCWD, path, AT_REMOVEDIR) | |
75 | } | |
76 | ||
77 | //sys symlinkat(oldpath string, newdirfd int, newpath string) (err error) | |
78 | ||
79 | func Symlink(oldpath string, newpath string) (err error) { | |
80 | return symlinkat(oldpath, AT_FDCWD, newpath) | |
81 | } | |
82 | ||
83 | func Unlink(path string) error { | |
84 | return unlinkat(AT_FDCWD, path, 0) | |
85 | } | |
86 | ||
87 | //sys unlinkat(dirfd int, path string, flags int) (err error) | |
88 | ||
89 | func Unlinkat(dirfd int, path string) error { | |
90 | return unlinkat(dirfd, path, 0) | |
91 | } | |
92 | ||
93 | //sys utimes(path string, times *[2]Timeval) (err error) | |
94 | ||
95 | func Utimes(path string, tv []Timeval) (err error) { | |
96 | if tv == nil { | |
97 | return utimes(path, nil) | |
98 | } | |
99 | if len(tv) != 2 { | |
100 | return EINVAL | |
101 | } | |
102 | return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) | |
103 | } | |
104 | ||
105 | //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) | |
106 | ||
107 | func UtimesNano(path string, ts []Timespec) error { | |
108 | if ts == nil { | |
109 | err := utimensat(AT_FDCWD, path, nil, 0) | |
110 | if err != ENOSYS { | |
111 | return err | |
112 | } | |
113 | return utimes(path, nil) | |
114 | } | |
115 | if len(ts) != 2 { | |
116 | return EINVAL | |
117 | } | |
118 | err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) | |
119 | if err != ENOSYS { | |
120 | return err | |
121 | } | |
122 | // If the utimensat syscall isn't available (utimensat was added to Linux | |
123 | // in 2.6.22, Released, 8 July 2007) then fall back to utimes | |
124 | var tv [2]Timeval | |
125 | for i := 0; i < 2; i++ { | |
126 | tv[i].Sec = ts[i].Sec | |
127 | tv[i].Usec = ts[i].Nsec / 1000 | |
128 | } | |
129 | return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) | |
130 | } | |
131 | ||
132 | func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error { | |
133 | if ts == nil { | |
134 | return utimensat(dirfd, path, nil, flags) | |
135 | } | |
136 | if len(ts) != 2 { | |
137 | return EINVAL | |
138 | } | |
139 | return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags) | |
140 | } | |
141 | ||
142 | //sys futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) | |
143 | ||
144 | func Futimesat(dirfd int, path string, tv []Timeval) error { | |
145 | pathp, err := BytePtrFromString(path) | |
146 | if err != nil { | |
147 | return err | |
148 | } | |
149 | if tv == nil { | |
150 | return futimesat(dirfd, pathp, nil) | |
151 | } | |
152 | if len(tv) != 2 { | |
153 | return EINVAL | |
154 | } | |
155 | return futimesat(dirfd, pathp, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) | |
156 | } | |
157 | ||
158 | func Futimes(fd int, tv []Timeval) (err error) { | |
159 | // Believe it or not, this is the best we can do on Linux | |
160 | // (and is what glibc does). | |
161 | return Utimes("/proc/self/fd/"+itoa(fd), tv) | |
162 | } | |
163 | ||
164 | const ImplementsGetwd = true | |
165 | ||
166 | //sys Getcwd(buf []byte) (n int, err error) | |
167 | ||
168 | func Getwd() (wd string, err error) { | |
169 | var buf [PathMax]byte | |
170 | n, err := Getcwd(buf[0:]) | |
171 | if err != nil { | |
172 | return "", err | |
173 | } | |
174 | // Getcwd returns the number of bytes written to buf, including the NUL. | |
175 | if n < 1 || n > len(buf) || buf[n-1] != 0 { | |
176 | return "", EINVAL | |
177 | } | |
178 | return string(buf[0 : n-1]), nil | |
179 | } | |
180 | ||
181 | func Getgroups() (gids []int, err error) { | |
182 | n, err := getgroups(0, nil) | |
183 | if err != nil { | |
184 | return nil, err | |
185 | } | |
186 | if n == 0 { | |
187 | return nil, nil | |
188 | } | |
189 | ||
190 | // Sanity check group count. Max is 1<<16 on Linux. | |
191 | if n < 0 || n > 1<<20 { | |
192 | return nil, EINVAL | |
193 | } | |
194 | ||
195 | a := make([]_Gid_t, n) | |
196 | n, err = getgroups(n, &a[0]) | |
197 | if err != nil { | |
198 | return nil, err | |
199 | } | |
200 | gids = make([]int, n) | |
201 | for i, v := range a[0:n] { | |
202 | gids[i] = int(v) | |
203 | } | |
204 | return | |
205 | } | |
206 | ||
207 | func Setgroups(gids []int) (err error) { | |
208 | if len(gids) == 0 { | |
209 | return setgroups(0, nil) | |
210 | } | |
211 | ||
212 | a := make([]_Gid_t, len(gids)) | |
213 | for i, v := range gids { | |
214 | a[i] = _Gid_t(v) | |
215 | } | |
216 | return setgroups(len(a), &a[0]) | |
217 | } | |
218 | ||
219 | type WaitStatus uint32 | |
220 | ||
221 | // Wait status is 7 bits at bottom, either 0 (exited), | |
222 | // 0x7F (stopped), or a signal number that caused an exit. | |
223 | // The 0x80 bit is whether there was a core dump. | |
224 | // An extra number (exit code, signal causing a stop) | |
225 | // is in the high bits. At least that's the idea. | |
226 | // There are various irregularities. For example, the | |
227 | // "continued" status is 0xFFFF, distinguishing itself | |
228 | // from stopped via the core dump bit. | |
229 | ||
230 | const ( | |
231 | mask = 0x7F | |
232 | core = 0x80 | |
233 | exited = 0x00 | |
234 | stopped = 0x7F | |
235 | shift = 8 | |
236 | ) | |
237 | ||
238 | func (w WaitStatus) Exited() bool { return w&mask == exited } | |
239 | ||
240 | func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited } | |
241 | ||
242 | func (w WaitStatus) Stopped() bool { return w&0xFF == stopped } | |
243 | ||
244 | func (w WaitStatus) Continued() bool { return w == 0xFFFF } | |
245 | ||
246 | func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } | |
247 | ||
248 | func (w WaitStatus) ExitStatus() int { | |
249 | if !w.Exited() { | |
250 | return -1 | |
251 | } | |
252 | return int(w>>shift) & 0xFF | |
253 | } | |
254 | ||
255 | func (w WaitStatus) Signal() syscall.Signal { | |
256 | if !w.Signaled() { | |
257 | return -1 | |
258 | } | |
259 | return syscall.Signal(w & mask) | |
260 | } | |
261 | ||
262 | func (w WaitStatus) StopSignal() syscall.Signal { | |
263 | if !w.Stopped() { | |
264 | return -1 | |
265 | } | |
266 | return syscall.Signal(w>>shift) & 0xFF | |
267 | } | |
268 | ||
269 | func (w WaitStatus) TrapCause() int { | |
270 | if w.StopSignal() != SIGTRAP { | |
271 | return -1 | |
272 | } | |
273 | return int(w>>shift) >> 8 | |
274 | } | |
275 | ||
276 | //sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) | |
277 | ||
278 | func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { | |
279 | var status _C_int | |
280 | wpid, err = wait4(pid, &status, options, rusage) | |
281 | if wstatus != nil { | |
282 | *wstatus = WaitStatus(status) | |
283 | } | |
284 | return | |
285 | } | |
286 | ||
287 | func Mkfifo(path string, mode uint32) (err error) { | |
288 | return Mknod(path, mode|S_IFIFO, 0) | |
289 | } | |
290 | ||
291 | func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { | |
292 | if sa.Port < 0 || sa.Port > 0xFFFF { | |
293 | return nil, 0, EINVAL | |
294 | } | |
295 | sa.raw.Family = AF_INET | |
296 | p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) | |
297 | p[0] = byte(sa.Port >> 8) | |
298 | p[1] = byte(sa.Port) | |
299 | for i := 0; i < len(sa.Addr); i++ { | |
300 | sa.raw.Addr[i] = sa.Addr[i] | |
301 | } | |
302 | return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil | |
303 | } | |
304 | ||
305 | func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { | |
306 | if sa.Port < 0 || sa.Port > 0xFFFF { | |
307 | return nil, 0, EINVAL | |
308 | } | |
309 | sa.raw.Family = AF_INET6 | |
310 | p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) | |
311 | p[0] = byte(sa.Port >> 8) | |
312 | p[1] = byte(sa.Port) | |
313 | sa.raw.Scope_id = sa.ZoneId | |
314 | for i := 0; i < len(sa.Addr); i++ { | |
315 | sa.raw.Addr[i] = sa.Addr[i] | |
316 | } | |
317 | return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil | |
318 | } | |
319 | ||
320 | func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { | |
321 | name := sa.Name | |
322 | n := len(name) | |
323 | if n >= len(sa.raw.Path) { | |
324 | return nil, 0, EINVAL | |
325 | } | |
326 | sa.raw.Family = AF_UNIX | |
327 | for i := 0; i < n; i++ { | |
328 | sa.raw.Path[i] = int8(name[i]) | |
329 | } | |
330 | // length is family (uint16), name, NUL. | |
331 | sl := _Socklen(2) | |
332 | if n > 0 { | |
333 | sl += _Socklen(n) + 1 | |
334 | } | |
335 | if sa.raw.Path[0] == '@' { | |
336 | sa.raw.Path[0] = 0 | |
337 | // Don't count trailing NUL for abstract address. | |
338 | sl-- | |
339 | } | |
340 | ||
341 | return unsafe.Pointer(&sa.raw), sl, nil | |
342 | } | |
343 | ||
344 | type SockaddrLinklayer struct { | |
345 | Protocol uint16 | |
346 | Ifindex int | |
347 | Hatype uint16 | |
348 | Pkttype uint8 | |
349 | Halen uint8 | |
350 | Addr [8]byte | |
351 | raw RawSockaddrLinklayer | |
352 | } | |
353 | ||
354 | func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) { | |
355 | if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff { | |
356 | return nil, 0, EINVAL | |
357 | } | |
358 | sa.raw.Family = AF_PACKET | |
359 | sa.raw.Protocol = sa.Protocol | |
360 | sa.raw.Ifindex = int32(sa.Ifindex) | |
361 | sa.raw.Hatype = sa.Hatype | |
362 | sa.raw.Pkttype = sa.Pkttype | |
363 | sa.raw.Halen = sa.Halen | |
364 | for i := 0; i < len(sa.Addr); i++ { | |
365 | sa.raw.Addr[i] = sa.Addr[i] | |
366 | } | |
367 | return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil | |
368 | } | |
369 | ||
370 | type SockaddrNetlink struct { | |
371 | Family uint16 | |
372 | Pad uint16 | |
373 | Pid uint32 | |
374 | Groups uint32 | |
375 | raw RawSockaddrNetlink | |
376 | } | |
377 | ||
378 | func (sa *SockaddrNetlink) sockaddr() (unsafe.Pointer, _Socklen, error) { | |
379 | sa.raw.Family = AF_NETLINK | |
380 | sa.raw.Pad = sa.Pad | |
381 | sa.raw.Pid = sa.Pid | |
382 | sa.raw.Groups = sa.Groups | |
383 | return unsafe.Pointer(&sa.raw), SizeofSockaddrNetlink, nil | |
384 | } | |
385 | ||
386 | func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { | |
387 | switch rsa.Addr.Family { | |
388 | case AF_NETLINK: | |
389 | pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa)) | |
390 | sa := new(SockaddrNetlink) | |
391 | sa.Family = pp.Family | |
392 | sa.Pad = pp.Pad | |
393 | sa.Pid = pp.Pid | |
394 | sa.Groups = pp.Groups | |
395 | return sa, nil | |
396 | ||
397 | case AF_PACKET: | |
398 | pp := (*RawSockaddrLinklayer)(unsafe.Pointer(rsa)) | |
399 | sa := new(SockaddrLinklayer) | |
400 | sa.Protocol = pp.Protocol | |
401 | sa.Ifindex = int(pp.Ifindex) | |
402 | sa.Hatype = pp.Hatype | |
403 | sa.Pkttype = pp.Pkttype | |
404 | sa.Halen = pp.Halen | |
405 | for i := 0; i < len(sa.Addr); i++ { | |
406 | sa.Addr[i] = pp.Addr[i] | |
407 | } | |
408 | return sa, nil | |
409 | ||
410 | case AF_UNIX: | |
411 | pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) | |
412 | sa := new(SockaddrUnix) | |
413 | if pp.Path[0] == 0 { | |
414 | // "Abstract" Unix domain socket. | |
415 | // Rewrite leading NUL as @ for textual display. | |
416 | // (This is the standard convention.) | |
417 | // Not friendly to overwrite in place, | |
418 | // but the callers below don't care. | |
419 | pp.Path[0] = '@' | |
420 | } | |
421 | ||
422 | // Assume path ends at NUL. | |
423 | // This is not technically the Linux semantics for | |
424 | // abstract Unix domain sockets--they are supposed | |
425 | // to be uninterpreted fixed-size binary blobs--but | |
426 | // everyone uses this convention. | |
427 | n := 0 | |
428 | for n < len(pp.Path) && pp.Path[n] != 0 { | |
429 | n++ | |
430 | } | |
431 | bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] | |
432 | sa.Name = string(bytes) | |
433 | return sa, nil | |
434 | ||
435 | case AF_INET: | |
436 | pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) | |
437 | sa := new(SockaddrInet4) | |
438 | p := (*[2]byte)(unsafe.Pointer(&pp.Port)) | |
439 | sa.Port = int(p[0])<<8 + int(p[1]) | |
440 | for i := 0; i < len(sa.Addr); i++ { | |
441 | sa.Addr[i] = pp.Addr[i] | |
442 | } | |
443 | return sa, nil | |
444 | ||
445 | case AF_INET6: | |
446 | pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) | |
447 | sa := new(SockaddrInet6) | |
448 | p := (*[2]byte)(unsafe.Pointer(&pp.Port)) | |
449 | sa.Port = int(p[0])<<8 + int(p[1]) | |
450 | sa.ZoneId = pp.Scope_id | |
451 | for i := 0; i < len(sa.Addr); i++ { | |
452 | sa.Addr[i] = pp.Addr[i] | |
453 | } | |
454 | return sa, nil | |
455 | } | |
456 | return nil, EAFNOSUPPORT | |
457 | } | |
458 | ||
459 | func Accept(fd int) (nfd int, sa Sockaddr, err error) { | |
460 | var rsa RawSockaddrAny | |
461 | var len _Socklen = SizeofSockaddrAny | |
462 | nfd, err = accept(fd, &rsa, &len) | |
463 | if err != nil { | |
464 | return | |
465 | } | |
466 | sa, err = anyToSockaddr(&rsa) | |
467 | if err != nil { | |
468 | Close(nfd) | |
469 | nfd = 0 | |
470 | } | |
471 | return | |
472 | } | |
473 | ||
474 | func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) { | |
475 | var rsa RawSockaddrAny | |
476 | var len _Socklen = SizeofSockaddrAny | |
477 | nfd, err = accept4(fd, &rsa, &len, flags) | |
478 | if err != nil { | |
479 | return | |
480 | } | |
481 | if len > SizeofSockaddrAny { | |
482 | panic("RawSockaddrAny too small") | |
483 | } | |
484 | sa, err = anyToSockaddr(&rsa) | |
485 | if err != nil { | |
486 | Close(nfd) | |
487 | nfd = 0 | |
488 | } | |
489 | return | |
490 | } | |
491 | ||
492 | func Getsockname(fd int) (sa Sockaddr, err error) { | |
493 | var rsa RawSockaddrAny | |
494 | var len _Socklen = SizeofSockaddrAny | |
495 | if err = getsockname(fd, &rsa, &len); err != nil { | |
496 | return | |
497 | } | |
498 | return anyToSockaddr(&rsa) | |
499 | } | |
500 | ||
501 | func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) { | |
502 | vallen := _Socklen(4) | |
503 | err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) | |
504 | return value, err | |
505 | } | |
506 | ||
507 | func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) { | |
508 | var value IPMreq | |
509 | vallen := _Socklen(SizeofIPMreq) | |
510 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | |
511 | return &value, err | |
512 | } | |
513 | ||
514 | func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) { | |
515 | var value IPMreqn | |
516 | vallen := _Socklen(SizeofIPMreqn) | |
517 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | |
518 | return &value, err | |
519 | } | |
520 | ||
521 | func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) { | |
522 | var value IPv6Mreq | |
523 | vallen := _Socklen(SizeofIPv6Mreq) | |
524 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | |
525 | return &value, err | |
526 | } | |
527 | ||
528 | func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) { | |
529 | var value IPv6MTUInfo | |
530 | vallen := _Socklen(SizeofIPv6MTUInfo) | |
531 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | |
532 | return &value, err | |
533 | } | |
534 | ||
535 | func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) { | |
536 | var value ICMPv6Filter | |
537 | vallen := _Socklen(SizeofICMPv6Filter) | |
538 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | |
539 | return &value, err | |
540 | } | |
541 | ||
542 | func GetsockoptUcred(fd, level, opt int) (*Ucred, error) { | |
543 | var value Ucred | |
544 | vallen := _Socklen(SizeofUcred) | |
545 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | |
546 | return &value, err | |
547 | } | |
548 | ||
549 | func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) { | |
550 | return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq)) | |
551 | } | |
552 | ||
553 | func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { | |
554 | var msg Msghdr | |
555 | var rsa RawSockaddrAny | |
556 | msg.Name = (*byte)(unsafe.Pointer(&rsa)) | |
557 | msg.Namelen = uint32(SizeofSockaddrAny) | |
558 | var iov Iovec | |
559 | if len(p) > 0 { | |
560 | iov.Base = (*byte)(unsafe.Pointer(&p[0])) | |
561 | iov.SetLen(len(p)) | |
562 | } | |
563 | var dummy byte | |
564 | if len(oob) > 0 { | |
565 | // receive at least one normal byte | |
566 | if len(p) == 0 { | |
567 | iov.Base = &dummy | |
568 | iov.SetLen(1) | |
569 | } | |
570 | msg.Control = (*byte)(unsafe.Pointer(&oob[0])) | |
571 | msg.SetControllen(len(oob)) | |
572 | } | |
573 | msg.Iov = &iov | |
574 | msg.Iovlen = 1 | |
575 | if n, err = recvmsg(fd, &msg, flags); err != nil { | |
576 | return | |
577 | } | |
578 | oobn = int(msg.Controllen) | |
579 | recvflags = int(msg.Flags) | |
580 | // source address is only specified if the socket is unconnected | |
581 | if rsa.Addr.Family != AF_UNSPEC { | |
582 | from, err = anyToSockaddr(&rsa) | |
583 | } | |
584 | return | |
585 | } | |
586 | ||
587 | func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { | |
588 | _, err = SendmsgN(fd, p, oob, to, flags) | |
589 | return | |
590 | } | |
591 | ||
592 | func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { | |
593 | var ptr unsafe.Pointer | |
594 | var salen _Socklen | |
595 | if to != nil { | |
596 | var err error | |
597 | ptr, salen, err = to.sockaddr() | |
598 | if err != nil { | |
599 | return 0, err | |
600 | } | |
601 | } | |
602 | var msg Msghdr | |
603 | msg.Name = (*byte)(unsafe.Pointer(ptr)) | |
604 | msg.Namelen = uint32(salen) | |
605 | var iov Iovec | |
606 | if len(p) > 0 { | |
607 | iov.Base = (*byte)(unsafe.Pointer(&p[0])) | |
608 | iov.SetLen(len(p)) | |
609 | } | |
610 | var dummy byte | |
611 | if len(oob) > 0 { | |
612 | // send at least one normal byte | |
613 | if len(p) == 0 { | |
614 | iov.Base = &dummy | |
615 | iov.SetLen(1) | |
616 | } | |
617 | msg.Control = (*byte)(unsafe.Pointer(&oob[0])) | |
618 | msg.SetControllen(len(oob)) | |
619 | } | |
620 | msg.Iov = &iov | |
621 | msg.Iovlen = 1 | |
622 | if n, err = sendmsg(fd, &msg, flags); err != nil { | |
623 | return 0, err | |
624 | } | |
625 | if len(oob) > 0 && len(p) == 0 { | |
626 | n = 0 | |
627 | } | |
628 | return n, nil | |
629 | } | |
630 | ||
631 | // BindToDevice binds the socket associated with fd to device. | |
632 | func BindToDevice(fd int, device string) (err error) { | |
633 | return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device) | |
634 | } | |
635 | ||
636 | //sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) | |
637 | ||
638 | func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) { | |
639 | // The peek requests are machine-size oriented, so we wrap it | |
640 | // to retrieve arbitrary-length data. | |
641 | ||
642 | // The ptrace syscall differs from glibc's ptrace. | |
643 | // Peeks returns the word in *data, not as the return value. | |
644 | ||
645 | var buf [sizeofPtr]byte | |
646 | ||
647 | // Leading edge. PEEKTEXT/PEEKDATA don't require aligned | |
648 | // access (PEEKUSER warns that it might), but if we don't | |
649 | // align our reads, we might straddle an unmapped page | |
650 | // boundary and not get the bytes leading up to the page | |
651 | // boundary. | |
652 | n := 0 | |
653 | if addr%sizeofPtr != 0 { | |
654 | err = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0]))) | |
655 | if err != nil { | |
656 | return 0, err | |
657 | } | |
658 | n += copy(out, buf[addr%sizeofPtr:]) | |
659 | out = out[n:] | |
660 | } | |
661 | ||
662 | // Remainder. | |
663 | for len(out) > 0 { | |
664 | // We use an internal buffer to guarantee alignment. | |
665 | // It's not documented if this is necessary, but we're paranoid. | |
666 | err = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0]))) | |
667 | if err != nil { | |
668 | return n, err | |
669 | } | |
670 | copied := copy(out, buf[0:]) | |
671 | n += copied | |
672 | out = out[copied:] | |
673 | } | |
674 | ||
675 | return n, nil | |
676 | } | |
677 | ||
678 | func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) { | |
679 | return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out) | |
680 | } | |
681 | ||
682 | func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) { | |
683 | return ptracePeek(PTRACE_PEEKDATA, pid, addr, out) | |
684 | } | |
685 | ||
686 | func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, err error) { | |
687 | // As for ptracePeek, we need to align our accesses to deal | |
688 | // with the possibility of straddling an invalid page. | |
689 | ||
690 | // Leading edge. | |
691 | n := 0 | |
692 | if addr%sizeofPtr != 0 { | |
693 | var buf [sizeofPtr]byte | |
694 | err = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0]))) | |
695 | if err != nil { | |
696 | return 0, err | |
697 | } | |
698 | n += copy(buf[addr%sizeofPtr:], data) | |
699 | word := *((*uintptr)(unsafe.Pointer(&buf[0]))) | |
700 | err = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word) | |
701 | if err != nil { | |
702 | return 0, err | |
703 | } | |
704 | data = data[n:] | |
705 | } | |
706 | ||
707 | // Interior. | |
708 | for len(data) > sizeofPtr { | |
709 | word := *((*uintptr)(unsafe.Pointer(&data[0]))) | |
710 | err = ptrace(pokeReq, pid, addr+uintptr(n), word) | |
711 | if err != nil { | |
712 | return n, err | |
713 | } | |
714 | n += sizeofPtr | |
715 | data = data[sizeofPtr:] | |
716 | } | |
717 | ||
718 | // Trailing edge. | |
719 | if len(data) > 0 { | |
720 | var buf [sizeofPtr]byte | |
721 | err = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0]))) | |
722 | if err != nil { | |
723 | return n, err | |
724 | } | |
725 | copy(buf[0:], data) | |
726 | word := *((*uintptr)(unsafe.Pointer(&buf[0]))) | |
727 | err = ptrace(pokeReq, pid, addr+uintptr(n), word) | |
728 | if err != nil { | |
729 | return n, err | |
730 | } | |
731 | n += len(data) | |
732 | } | |
733 | ||
734 | return n, nil | |
735 | } | |
736 | ||
737 | func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) { | |
738 | return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data) | |
739 | } | |
740 | ||
741 | func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) { | |
742 | return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data) | |
743 | } | |
744 | ||
745 | func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) { | |
746 | return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) | |
747 | } | |
748 | ||
749 | func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) { | |
750 | return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) | |
751 | } | |
752 | ||
753 | func PtraceSetOptions(pid int, options int) (err error) { | |
754 | return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options)) | |
755 | } | |
756 | ||
757 | func PtraceGetEventMsg(pid int) (msg uint, err error) { | |
758 | var data _C_long | |
759 | err = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data))) | |
760 | msg = uint(data) | |
761 | return | |
762 | } | |
763 | ||
764 | func PtraceCont(pid int, signal int) (err error) { | |
765 | return ptrace(PTRACE_CONT, pid, 0, uintptr(signal)) | |
766 | } | |
767 | ||
768 | func PtraceSyscall(pid int, signal int) (err error) { | |
769 | return ptrace(PTRACE_SYSCALL, pid, 0, uintptr(signal)) | |
770 | } | |
771 | ||
772 | func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) } | |
773 | ||
774 | func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) } | |
775 | ||
776 | func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) } | |
777 | ||
778 | //sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) | |
779 | ||
780 | func Reboot(cmd int) (err error) { | |
781 | return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "") | |
782 | } | |
783 | ||
784 | func clen(n []byte) int { | |
785 | for i := 0; i < len(n); i++ { | |
786 | if n[i] == 0 { | |
787 | return i | |
788 | } | |
789 | } | |
790 | return len(n) | |
791 | } | |
792 | ||
793 | func ReadDirent(fd int, buf []byte) (n int, err error) { | |
794 | return Getdents(fd, buf) | |
795 | } | |
796 | ||
797 | func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) { | |
798 | origlen := len(buf) | |
799 | count = 0 | |
800 | for max != 0 && len(buf) > 0 { | |
801 | dirent := (*Dirent)(unsafe.Pointer(&buf[0])) | |
802 | buf = buf[dirent.Reclen:] | |
803 | if dirent.Ino == 0 { // File absent in directory. | |
804 | continue | |
805 | } | |
806 | bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0])) | |
807 | var name = string(bytes[0:clen(bytes[:])]) | |
808 | if name == "." || name == ".." { // Useless names | |
809 | continue | |
810 | } | |
811 | max-- | |
812 | count++ | |
813 | names = append(names, name) | |
814 | } | |
815 | return origlen - len(buf), count, names | |
816 | } | |
817 | ||
818 | //sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) | |
819 | ||
820 | func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { | |
821 | // Certain file systems get rather angry and EINVAL if you give | |
822 | // them an empty string of data, rather than NULL. | |
823 | if data == "" { | |
824 | return mount(source, target, fstype, flags, nil) | |
825 | } | |
826 | datap, err := BytePtrFromString(data) | |
827 | if err != nil { | |
828 | return err | |
829 | } | |
830 | return mount(source, target, fstype, flags, datap) | |
831 | } | |
832 | ||
833 | // Sendto | |
834 | // Recvfrom | |
835 | // Socketpair | |
836 | ||
837 | /* | |
838 | * Direct access | |
839 | */ | |
840 | //sys Acct(path string) (err error) | |
841 | //sys Adjtimex(buf *Timex) (state int, err error) | |
842 | //sys Chdir(path string) (err error) | |
843 | //sys Chroot(path string) (err error) | |
844 | //sys ClockGettime(clockid int32, time *Timespec) (err error) | |
845 | //sys Close(fd int) (err error) | |
846 | //sys Dup(oldfd int) (fd int, err error) | |
847 | //sys Dup3(oldfd int, newfd int, flags int) (err error) | |
848 | //sysnb EpollCreate(size int) (fd int, err error) | |
849 | //sysnb EpollCreate1(flag int) (fd int, err error) | |
850 | //sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) | |
851 | //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) | |
852 | //sys Exit(code int) = SYS_EXIT_GROUP | |
853 | //sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) | |
854 | //sys Fallocate(fd int, mode uint32, off int64, len int64) (err error) | |
855 | //sys Fchdir(fd int) (err error) | |
856 | //sys Fchmod(fd int, mode uint32) (err error) | |
857 | //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) | |
858 | //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) | |
859 | //sys fcntl(fd int, cmd int, arg int) (val int, err error) | |
860 | //sys Fdatasync(fd int) (err error) | |
861 | //sys Flock(fd int, how int) (err error) | |
862 | //sys Fsync(fd int) (err error) | |
863 | //sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64 | |
864 | //sysnb Getpgid(pid int) (pgid int, err error) | |
865 | ||
866 | func Getpgrp() (pid int) { | |
867 | pid, _ = Getpgid(0) | |
868 | return | |
869 | } | |
870 | ||
871 | //sysnb Getpid() (pid int) | |
872 | //sysnb Getppid() (ppid int) | |
873 | //sys Getpriority(which int, who int) (prio int, err error) | |
874 | //sysnb Getrusage(who int, rusage *Rusage) (err error) | |
875 | //sysnb Gettid() (tid int) | |
876 | //sys Getxattr(path string, attr string, dest []byte) (sz int, err error) | |
877 | //sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) | |
878 | //sysnb InotifyInit1(flags int) (fd int, err error) | |
879 | //sysnb InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) | |
880 | //sysnb Kill(pid int, sig syscall.Signal) (err error) | |
881 | //sys Klogctl(typ int, buf []byte) (n int, err error) = SYS_SYSLOG | |
882 | //sys Listxattr(path string, dest []byte) (sz int, err error) | |
883 | //sys Mkdirat(dirfd int, path string, mode uint32) (err error) | |
884 | //sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) | |
885 | //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) | |
886 | //sys Pause() (err error) | |
887 | //sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT | |
888 | //sysnb prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64 | |
889 | //sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) | |
890 | //sys read(fd int, p []byte) (n int, err error) | |
891 | //sys Removexattr(path string, attr string) (err error) | |
892 | //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) | |
893 | //sys Setdomainname(p []byte) (err error) | |
894 | //sys Sethostname(p []byte) (err error) | |
895 | //sysnb Setpgid(pid int, pgid int) (err error) | |
896 | //sysnb Setsid() (pid int, err error) | |
897 | //sysnb Settimeofday(tv *Timeval) (err error) | |
898 | ||
899 | // issue 1435. | |
900 | // On linux Setuid and Setgid only affects the current thread, not the process. | |
901 | // This does not match what most callers expect so we must return an error | |
902 | // here rather than letting the caller think that the call succeeded. | |
903 | ||
904 | func Setuid(uid int) (err error) { | |
905 | return EOPNOTSUPP | |
906 | } | |
907 | ||
908 | func Setgid(uid int) (err error) { | |
909 | return EOPNOTSUPP | |
910 | } | |
911 | ||
912 | //sys Setpriority(which int, who int, prio int) (err error) | |
913 | //sys Setxattr(path string, attr string, data []byte, flags int) (err error) | |
914 | //sys Sync() | |
915 | //sysnb Sysinfo(info *Sysinfo_t) (err error) | |
916 | //sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error) | |
917 | //sysnb Tgkill(tgid int, tid int, sig syscall.Signal) (err error) | |
918 | //sysnb Times(tms *Tms) (ticks uintptr, err error) | |
919 | //sysnb Umask(mask int) (oldmask int) | |
920 | //sysnb Uname(buf *Utsname) (err error) | |
921 | //sys Unmount(target string, flags int) (err error) = SYS_UMOUNT2 | |
922 | //sys Unshare(flags int) (err error) | |
923 | //sys Ustat(dev int, ubuf *Ustat_t) (err error) | |
924 | //sys Utime(path string, buf *Utimbuf) (err error) | |
925 | //sys write(fd int, p []byte) (n int, err error) | |
926 | //sys exitThread(code int) (err error) = SYS_EXIT | |
927 | //sys readlen(fd int, p *byte, np int) (n int, err error) = SYS_READ | |
928 | //sys writelen(fd int, p *byte, np int) (n int, err error) = SYS_WRITE | |
929 | ||
930 | // mmap varies by architecture; see syscall_linux_*.go. | |
931 | //sys munmap(addr uintptr, length uintptr) (err error) | |
932 | ||
933 | var mapper = &mmapper{ | |
934 | active: make(map[*byte][]byte), | |
935 | mmap: mmap, | |
936 | munmap: munmap, | |
937 | } | |
938 | ||
939 | func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { | |
940 | return mapper.Mmap(fd, offset, length, prot, flags) | |
941 | } | |
942 | ||
943 | func Munmap(b []byte) (err error) { | |
944 | return mapper.Munmap(b) | |
945 | } | |
946 | ||
947 | //sys Madvise(b []byte, advice int) (err error) | |
948 | //sys Mprotect(b []byte, prot int) (err error) | |
949 | //sys Mlock(b []byte) (err error) | |
950 | //sys Munlock(b []byte) (err error) | |
951 | //sys Mlockall(flags int) (err error) | |
952 | //sys Munlockall() (err error) | |
953 | ||
954 | /* | |
955 | * Unimplemented | |
956 | */ | |
957 | // AddKey | |
958 | // AfsSyscall | |
959 | // Alarm | |
960 | // ArchPrctl | |
961 | // Brk | |
962 | // Capget | |
963 | // Capset | |
964 | // ClockGetres | |
965 | // ClockNanosleep | |
966 | // ClockSettime | |
967 | // Clone | |
968 | // CreateModule | |
969 | // DeleteModule | |
970 | // EpollCtlOld | |
971 | // EpollPwait | |
972 | // EpollWaitOld | |
973 | // Eventfd | |
974 | // Execve | |
975 | // Fgetxattr | |
976 | // Flistxattr | |
977 | // Fork | |
978 | // Fremovexattr | |
979 | // Fsetxattr | |
980 | // Futex | |
981 | // GetKernelSyms | |
982 | // GetMempolicy | |
983 | // GetRobustList | |
984 | // GetThreadArea | |
985 | // Getitimer | |
986 | // Getpmsg | |
987 | // IoCancel | |
988 | // IoDestroy | |
989 | // IoGetevents | |
990 | // IoSetup | |
991 | // IoSubmit | |
992 | // Ioctl | |
993 | // IoprioGet | |
994 | // IoprioSet | |
995 | // KexecLoad | |
996 | // Keyctl | |
997 | // Lgetxattr | |
998 | // Llistxattr | |
999 | // LookupDcookie | |
1000 | // Lremovexattr | |
1001 | // Lsetxattr | |
1002 | // Mbind | |
1003 | // MigratePages | |
1004 | // Mincore | |
1005 | // ModifyLdt | |
1006 | // Mount | |
1007 | // MovePages | |
1008 | // Mprotect | |
1009 | // MqGetsetattr | |
1010 | // MqNotify | |
1011 | // MqOpen | |
1012 | // MqTimedreceive | |
1013 | // MqTimedsend | |
1014 | // MqUnlink | |
1015 | // Mremap | |
1016 | // Msgctl | |
1017 | // Msgget | |
1018 | // Msgrcv | |
1019 | // Msgsnd | |
1020 | // Msync | |
1021 | // Newfstatat | |
1022 | // Nfsservctl | |
1023 | // Personality | |
1024 | // Poll | |
1025 | // Ppoll | |
1026 | // Pselect6 | |
1027 | // Ptrace | |
1028 | // Putpmsg | |
1029 | // QueryModule | |
1030 | // Quotactl | |
1031 | // Readahead | |
1032 | // Readv | |
1033 | // RemapFilePages | |
1034 | // RequestKey | |
1035 | // RestartSyscall | |
1036 | // RtSigaction | |
1037 | // RtSigpending | |
1038 | // RtSigprocmask | |
1039 | // RtSigqueueinfo | |
1040 | // RtSigreturn | |
1041 | // RtSigsuspend | |
1042 | // RtSigtimedwait | |
1043 | // SchedGetPriorityMax | |
1044 | // SchedGetPriorityMin | |
1045 | // SchedGetaffinity | |
1046 | // SchedGetparam | |
1047 | // SchedGetscheduler | |
1048 | // SchedRrGetInterval | |
1049 | // SchedSetaffinity | |
1050 | // SchedSetparam | |
1051 | // SchedYield | |
1052 | // Security | |
1053 | // Semctl | |
1054 | // Semget | |
1055 | // Semop | |
1056 | // Semtimedop | |
1057 | // SetMempolicy | |
1058 | // SetRobustList | |
1059 | // SetThreadArea | |
1060 | // SetTidAddress | |
1061 | // Shmat | |
1062 | // Shmctl | |
1063 | // Shmdt | |
1064 | // Shmget | |
1065 | // Sigaltstack | |
1066 | // Signalfd | |
1067 | // Swapoff | |
1068 | // Swapon | |
1069 | // Sysfs | |
1070 | // TimerCreate | |
1071 | // TimerDelete | |
1072 | // TimerGetoverrun | |
1073 | // TimerGettime | |
1074 | // TimerSettime | |
1075 | // Timerfd | |
1076 | // Tkill (obsolete) | |
1077 | // Tuxcall | |
1078 | // Umount2 | |
1079 | // Uselib | |
1080 | // Utimensat | |
1081 | // Vfork | |
1082 | // Vhangup | |
1083 | // Vmsplice | |
1084 | // Vserver | |
1085 | // Waitid | |
1086 | // _Sysctl |