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