]>
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 | // TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP) | |
6 | // so that go vet can check that they are correct. | |
7 | ||
8 | // +build 386,linux | |
9 | ||
10 | package unix | |
11 | ||
12 | import ( | |
13 | "syscall" | |
14 | "unsafe" | |
15 | ) | |
16 | ||
17 | func Getpagesize() int { return 4096 } | |
18 | ||
19 | func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } | |
20 | ||
21 | func NsecToTimespec(nsec int64) (ts Timespec) { | |
22 | ts.Sec = int32(nsec / 1e9) | |
23 | ts.Nsec = int32(nsec % 1e9) | |
24 | return | |
25 | } | |
26 | ||
27 | func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 } | |
28 | ||
29 | func NsecToTimeval(nsec int64) (tv Timeval) { | |
30 | nsec += 999 // round up to microsecond | |
31 | tv.Sec = int32(nsec / 1e9) | |
32 | tv.Usec = int32(nsec % 1e9 / 1e3) | |
33 | return | |
34 | } | |
35 | ||
36 | //sysnb pipe(p *[2]_C_int) (err error) | |
37 | ||
38 | func Pipe(p []int) (err error) { | |
39 | if len(p) != 2 { | |
40 | return EINVAL | |
41 | } | |
42 | var pp [2]_C_int | |
43 | err = pipe(&pp) | |
44 | p[0] = int(pp[0]) | |
45 | p[1] = int(pp[1]) | |
46 | return | |
47 | } | |
48 | ||
49 | //sysnb pipe2(p *[2]_C_int, flags int) (err error) | |
50 | ||
51 | func Pipe2(p []int, flags int) (err error) { | |
52 | if len(p) != 2 { | |
53 | return EINVAL | |
54 | } | |
55 | var pp [2]_C_int | |
56 | err = pipe2(&pp, flags) | |
57 | p[0] = int(pp[0]) | |
58 | p[1] = int(pp[1]) | |
59 | return | |
60 | } | |
61 | ||
62 | // 64-bit file system and 32-bit uid calls | |
63 | // (386 default is 32-bit file system and 16-bit uid). | |
64 | //sys Dup2(oldfd int, newfd int) (err error) | |
65 | //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64 | |
66 | //sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32 | |
67 | //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 | |
68 | //sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64 | |
69 | //sysnb Getegid() (egid int) = SYS_GETEGID32 | |
70 | //sysnb Geteuid() (euid int) = SYS_GETEUID32 | |
71 | //sysnb Getgid() (gid int) = SYS_GETGID32 | |
72 | //sysnb Getuid() (uid int) = SYS_GETUID32 | |
73 | //sysnb InotifyInit() (fd int, err error) | |
74 | //sys Ioperm(from int, num int, on int) (err error) | |
75 | //sys Iopl(level int) (err error) | |
76 | //sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32 | |
77 | //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 | |
78 | //sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 | |
79 | //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 | |
80 | //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64 | |
81 | //sys Setfsgid(gid int) (err error) = SYS_SETFSGID32 | |
82 | //sys Setfsuid(uid int) (err error) = SYS_SETFSUID32 | |
83 | //sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32 | |
84 | //sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32 | |
85 | //sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32 | |
86 | //sysnb Setreuid(ruid int, euid int) (err error) = SYS_SETREUID32 | |
87 | //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) | |
88 | //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 | |
89 | //sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) | |
90 | //sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64 | |
91 | //sysnb getgroups(n int, list *_Gid_t) (nn int, err error) = SYS_GETGROUPS32 | |
92 | //sysnb setgroups(n int, list *_Gid_t) (err error) = SYS_SETGROUPS32 | |
93 | //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT | |
94 | ||
95 | //sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) | |
96 | ||
97 | func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { | |
98 | page := uintptr(offset / 4096) | |
99 | if offset != int64(page)*4096 { | |
100 | return 0, EINVAL | |
101 | } | |
102 | return mmap2(addr, length, prot, flags, fd, page) | |
103 | } | |
104 | ||
105 | type rlimit32 struct { | |
106 | Cur uint32 | |
107 | Max uint32 | |
108 | } | |
109 | ||
110 | //sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT | |
111 | ||
112 | const rlimInf32 = ^uint32(0) | |
113 | const rlimInf64 = ^uint64(0) | |
114 | ||
115 | func Getrlimit(resource int, rlim *Rlimit) (err error) { | |
116 | err = prlimit(0, resource, nil, rlim) | |
117 | if err != ENOSYS { | |
118 | return err | |
119 | } | |
120 | ||
121 | rl := rlimit32{} | |
122 | err = getrlimit(resource, &rl) | |
123 | if err != nil { | |
124 | return | |
125 | } | |
126 | ||
127 | if rl.Cur == rlimInf32 { | |
128 | rlim.Cur = rlimInf64 | |
129 | } else { | |
130 | rlim.Cur = uint64(rl.Cur) | |
131 | } | |
132 | ||
133 | if rl.Max == rlimInf32 { | |
134 | rlim.Max = rlimInf64 | |
135 | } else { | |
136 | rlim.Max = uint64(rl.Max) | |
137 | } | |
138 | return | |
139 | } | |
140 | ||
141 | //sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT | |
142 | ||
143 | func Setrlimit(resource int, rlim *Rlimit) (err error) { | |
144 | err = prlimit(0, resource, rlim, nil) | |
145 | if err != ENOSYS { | |
146 | return err | |
147 | } | |
148 | ||
149 | rl := rlimit32{} | |
150 | if rlim.Cur == rlimInf64 { | |
151 | rl.Cur = rlimInf32 | |
152 | } else if rlim.Cur < uint64(rlimInf32) { | |
153 | rl.Cur = uint32(rlim.Cur) | |
154 | } else { | |
155 | return EINVAL | |
156 | } | |
157 | if rlim.Max == rlimInf64 { | |
158 | rl.Max = rlimInf32 | |
159 | } else if rlim.Max < uint64(rlimInf32) { | |
160 | rl.Max = uint32(rlim.Max) | |
161 | } else { | |
162 | return EINVAL | |
163 | } | |
164 | ||
165 | return setrlimit(resource, &rl) | |
166 | } | |
167 | ||
168 | // Underlying system call writes to newoffset via pointer. | |
169 | // Implemented in assembly to avoid allocation. | |
170 | func seek(fd int, offset int64, whence int) (newoffset int64, err syscall.Errno) | |
171 | ||
172 | func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { | |
173 | newoffset, errno := seek(fd, offset, whence) | |
174 | if errno != 0 { | |
175 | return 0, errno | |
176 | } | |
177 | return newoffset, nil | |
178 | } | |
179 | ||
180 | // Vsyscalls on amd64. | |
181 | //sysnb Gettimeofday(tv *Timeval) (err error) | |
182 | //sysnb Time(t *Time_t) (tt Time_t, err error) | |
183 | ||
184 | // On x86 Linux, all the socket calls go through an extra indirection, | |
185 | // I think because the 5-register system call interface can't handle | |
186 | // the 6-argument calls like sendto and recvfrom. Instead the | |
187 | // arguments to the underlying system call are the number below | |
188 | // and a pointer to an array of uintptr. We hide the pointer in the | |
189 | // socketcall assembly to avoid allocation on every system call. | |
190 | ||
191 | const ( | |
192 | // see linux/net.h | |
193 | _SOCKET = 1 | |
194 | _BIND = 2 | |
195 | _CONNECT = 3 | |
196 | _LISTEN = 4 | |
197 | _ACCEPT = 5 | |
198 | _GETSOCKNAME = 6 | |
199 | _GETPEERNAME = 7 | |
200 | _SOCKETPAIR = 8 | |
201 | _SEND = 9 | |
202 | _RECV = 10 | |
203 | _SENDTO = 11 | |
204 | _RECVFROM = 12 | |
205 | _SHUTDOWN = 13 | |
206 | _SETSOCKOPT = 14 | |
207 | _GETSOCKOPT = 15 | |
208 | _SENDMSG = 16 | |
209 | _RECVMSG = 17 | |
210 | _ACCEPT4 = 18 | |
211 | _RECVMMSG = 19 | |
212 | _SENDMMSG = 20 | |
213 | ) | |
214 | ||
215 | func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err syscall.Errno) | |
216 | func rawsocketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err syscall.Errno) | |
217 | ||
218 | func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { | |
219 | fd, e := socketcall(_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0) | |
220 | if e != 0 { | |
221 | err = e | |
222 | } | |
223 | return | |
224 | } | |
225 | ||
226 | func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { | |
227 | fd, e := socketcall(_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) | |
228 | if e != 0 { | |
229 | err = e | |
230 | } | |
231 | return | |
232 | } | |
233 | ||
234 | func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { | |
235 | _, e := rawsocketcall(_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0) | |
236 | if e != 0 { | |
237 | err = e | |
238 | } | |
239 | return | |
240 | } | |
241 | ||
242 | func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { | |
243 | _, e := rawsocketcall(_GETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0) | |
244 | if e != 0 { | |
245 | err = e | |
246 | } | |
247 | return | |
248 | } | |
249 | ||
250 | func socketpair(domain int, typ int, flags int, fd *[2]int32) (err error) { | |
251 | _, e := rawsocketcall(_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(flags), uintptr(unsafe.Pointer(fd)), 0, 0) | |
252 | if e != 0 { | |
253 | err = e | |
254 | } | |
255 | return | |
256 | } | |
257 | ||
258 | func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { | |
259 | _, e := socketcall(_BIND, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0) | |
260 | if e != 0 { | |
261 | err = e | |
262 | } | |
263 | return | |
264 | } | |
265 | ||
266 | func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { | |
267 | _, e := socketcall(_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0) | |
268 | if e != 0 { | |
269 | err = e | |
270 | } | |
271 | return | |
272 | } | |
273 | ||
274 | func socket(domain int, typ int, proto int) (fd int, err error) { | |
275 | fd, e := rawsocketcall(_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0) | |
276 | if e != 0 { | |
277 | err = e | |
278 | } | |
279 | return | |
280 | } | |
281 | ||
282 | func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { | |
283 | _, e := socketcall(_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) | |
284 | if e != 0 { | |
285 | err = e | |
286 | } | |
287 | return | |
288 | } | |
289 | ||
290 | func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { | |
291 | _, e := socketcall(_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), vallen, 0) | |
292 | if e != 0 { | |
293 | err = e | |
294 | } | |
295 | return | |
296 | } | |
297 | ||
298 | func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { | |
299 | var base uintptr | |
300 | if len(p) > 0 { | |
301 | base = uintptr(unsafe.Pointer(&p[0])) | |
302 | } | |
303 | n, e := socketcall(_RECVFROM, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) | |
304 | if e != 0 { | |
305 | err = e | |
306 | } | |
307 | return | |
308 | } | |
309 | ||
310 | func sendto(s int, p []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { | |
311 | var base uintptr | |
312 | if len(p) > 0 { | |
313 | base = uintptr(unsafe.Pointer(&p[0])) | |
314 | } | |
315 | _, e := socketcall(_SENDTO, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(to), uintptr(addrlen)) | |
316 | if e != 0 { | |
317 | err = e | |
318 | } | |
319 | return | |
320 | } | |
321 | ||
322 | func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { | |
323 | n, e := socketcall(_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0) | |
324 | if e != 0 { | |
325 | err = e | |
326 | } | |
327 | return | |
328 | } | |
329 | ||
330 | func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { | |
331 | n, e := socketcall(_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0) | |
332 | if e != 0 { | |
333 | err = e | |
334 | } | |
335 | return | |
336 | } | |
337 | ||
338 | func Listen(s int, n int) (err error) { | |
339 | _, e := socketcall(_LISTEN, uintptr(s), uintptr(n), 0, 0, 0, 0) | |
340 | if e != 0 { | |
341 | err = e | |
342 | } | |
343 | return | |
344 | } | |
345 | ||
346 | func Shutdown(s, how int) (err error) { | |
347 | _, e := socketcall(_SHUTDOWN, uintptr(s), uintptr(how), 0, 0, 0, 0) | |
348 | if e != 0 { | |
349 | err = e | |
350 | } | |
351 | return | |
352 | } | |
353 | ||
354 | func Fstatfs(fd int, buf *Statfs_t) (err error) { | |
355 | _, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf))) | |
356 | if e != 0 { | |
357 | err = e | |
358 | } | |
359 | return | |
360 | } | |
361 | ||
362 | func Statfs(path string, buf *Statfs_t) (err error) { | |
363 | pathp, err := BytePtrFromString(path) | |
364 | if err != nil { | |
365 | return err | |
366 | } | |
367 | _, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(pathp)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf))) | |
368 | if e != 0 { | |
369 | err = e | |
370 | } | |
371 | return | |
372 | } | |
373 | ||
374 | func (r *PtraceRegs) PC() uint64 { return uint64(uint32(r.Eip)) } | |
375 | ||
376 | func (r *PtraceRegs) SetPC(pc uint64) { r.Eip = int32(pc) } | |
377 | ||
378 | func (iov *Iovec) SetLen(length int) { | |
379 | iov.Len = uint32(length) | |
380 | } | |
381 | ||
382 | func (msghdr *Msghdr) SetControllen(length int) { | |
383 | msghdr.Controllen = uint32(length) | |
384 | } | |
385 | ||
386 | func (cmsg *Cmsghdr) SetLen(length int) { | |
387 | cmsg.Len = uint32(length) | |
388 | } |