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