1#include "defs.h"
2
3#include "xlat/whence_codes.h"
4
5/* Linux kernel has exactly one version of lseek:
6 * fs/read_write.c::SYSCALL_DEFINE3(lseek, unsigned, fd, off_t, offset, unsigned, origin)
7 * In kernel, off_t is always the same as (kernel's) long
8 * (see include/uapi/asm-generic/posix_types.h),
9 * which means that on x32 we need to use tcp->ext_arg[N] to get offset argument.
10 * Use test/x32_lseek.c to test lseek decoding.
11 */
12#if defined(LINUX_MIPSN32) || defined(X32)
13SYS_FUNC(lseek)
14{
15	long long offset;
16	int whence;
17
18	if (entering(tcp)) {
19		printfd(tcp, tcp->u_arg[0]);
20		offset = tcp->ext_arg[1];
21		whence = tcp->u_arg[2];
22		if (whence == SEEK_SET)
23			tprintf(", %llu, ", offset);
24		else
25			tprintf(", %lld, ", offset);
26		printxval(whence_codes, whence, "SEEK_???");
27	}
28	return RVAL_LUDECIMAL;
29}
30#else
31SYS_FUNC(lseek)
32{
33	long offset;
34	int whence;
35
36	if (entering(tcp)) {
37		printfd(tcp, tcp->u_arg[0]);
38		offset = tcp->u_arg[1];
39		whence = tcp->u_arg[2];
40		if (whence == SEEK_SET)
41			tprintf(", %lu, ", offset);
42		else
43			tprintf(", %ld, ", offset);
44		printxval(whence_codes, whence, "SEEK_???");
45	}
46	return RVAL_UDECIMAL;
47}
48#endif
49
50/* llseek syscall takes explicitly two ulong arguments hi, lo,
51 * rather than one 64-bit argument for which LONG_LONG works
52 * appropriate for the native byte order.
53 *
54 * See kernel's fs/read_write.c::SYSCALL_DEFINE5(llseek, ...)
55 *
56 * hi,lo are "unsigned longs" and combined exactly this way in kernel:
57 * ((loff_t) hi << 32) | lo
58 * Note that for architectures with kernel's long wider than userspace long
59 * (such as x32), combining code will use *kernel's*, i.e. *wide* longs
60 * for hi and lo. We would need to use tcp->ext_arg[N] on x32...
61 * ...however, x32 (and x86_64) does not _have_ llseek syscall as such.
62 */
63SYS_FUNC(llseek)
64{
65	if (entering(tcp)) {
66		printfd(tcp, tcp->u_arg[0]);
67		if (tcp->u_arg[4] == SEEK_SET)
68			tprintf(", %llu, ",
69				((long long) tcp->u_arg[1]) << 32 |
70				(unsigned long long) (unsigned) tcp->u_arg[2]);
71		else
72			tprintf(", %lld, ",
73				((long long) tcp->u_arg[1]) << 32 |
74				(unsigned long long) (unsigned) tcp->u_arg[2]);
75	}
76	else {
77		long long off;
78		if (syserror(tcp) || umove(tcp, tcp->u_arg[3], &off) < 0)
79			tprintf("%#lx, ", tcp->u_arg[3]);
80		else
81			tprintf("[%llu], ", off);
82		printxval(whence_codes, tcp->u_arg[4], "SEEK_???");
83	}
84	return 0;
85}
86