Comment inner workings of sys_[l]lseek

The code doesn't look fully correct to me, but I need to experiment
on actual x32 machine before I start "fixing" things.
For now, add comments, and optimize out one tprints() call...

* file.c (sys_lseek): Rename '_whence' as 'whence'.
Merge printing of ", " into subsequent tprintf.
(sys_lseek32): Likewise.
(sys_llseek): Likewise.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2013-02-17 01:38:14 +01:00
parent a32086f2aa
commit 386b871b0a

68
file.c
View File

@ -523,23 +523,28 @@ static const struct xlat whence[] = {
{ 0, NULL },
};
/* Linux kernel has exactly one version of lseek:
* fs/read_write.c::SYSCALL_DEFINE3(lseek, unsigned, fd, off_t, offset, unsigned, origin)
* In kernel, off_t is always the same as (kernel's) long
* (see include/uapi/asm-generic/posix_types.h),
* which means that on x32 we need to use tcp->ext_arg[N] to get offset argument.
*/
#if defined(LINUX_MIPSN32) || defined(X32)
int
sys_lseek(struct tcb *tcp)
{
long long offset;
int _whence;
int whence;
if (entering(tcp)) {
printfd(tcp, tcp->u_arg[0]);
tprints(", ");
offset = tcp->ext_arg[1];
_whence = tcp->u_arg[2];
if (_whence == SEEK_SET)
tprintf("%llu, ", offset);
whence = tcp->u_arg[2];
if (whence == SEEK_SET)
tprintf(", %llu, ", offset);
else
tprintf("%lld, ", offset);
printxval(whence, _whence, "SEEK_???");
tprintf(", %lld, ", offset);
printxval(whence, whence, "SEEK_???");
}
return RVAL_LUDECIMAL;
}
@ -549,18 +554,17 @@ int
sys_lseek32(struct tcb *tcp)
{
long offset;
int _whence;
int whence;
if (entering(tcp)) {
printfd(tcp, tcp->u_arg[0]);
tprints(", ");
offset = tcp->u_arg[1];
_whence = tcp->u_arg[2];
if (_whence == SEEK_SET)
tprintf("%lu, ", offset);
whence = tcp->u_arg[2];
if (whence == SEEK_SET)
tprintf(", %lu, ", offset);
else
tprintf("%ld, ", offset);
printxval(whence, _whence, "SEEK_???");
tprintf(", %ld, ", offset);
printxval(whence, whence, "SEEK_???");
}
return RVAL_UDECIMAL;
}
@ -570,44 +574,50 @@ int
sys_lseek(struct tcb *tcp)
{
off_t offset;
int _whence;
int whence;
if (entering(tcp)) {
printfd(tcp, tcp->u_arg[0]);
tprints(", ");
offset = tcp->u_arg[1];
_whence = tcp->u_arg[2];
if (_whence == SEEK_SET)
tprintf("%lu, ", offset);
whence = tcp->u_arg[2];
if (whence == SEEK_SET)
tprintf(", %lu, ", offset);
else
tprintf("%ld, ", offset);
printxval(whence, _whence, "SEEK_???");
tprintf(", %ld, ", offset);
printxval(whence, whence, "SEEK_???");
}
return RVAL_UDECIMAL;
}
#endif
/* llseek syscall takes explicitly two ulong arguments hi, lo,
* rather than one 64-bit argument for which LONG_LONG works
* appropriate for the native byte order.
*
* See kernel's fs/read_write.c::SYSCALL_DEFINE5(llseek, ...)
*
* hi,lo are "unsigned longs" and combined exactly this way in kernel:
* ((loff_t) hi << 32) | lo
* Note that for architectures with kernel's long wider than userspace longs
* (such as x32), combining code will use *kernel's*, i.e. *wide* longs
* for hi and lo. You may need to use tcp->ext_arg[N]!
*/
int
sys_llseek(struct tcb *tcp)
{
if (entering(tcp)) {
printfd(tcp, tcp->u_arg[0]);
/*
* This one call takes explicitly two 32-bit arguments hi, lo,
* rather than one 64-bit argument for which LONG_LONG works
* appropriate for the native byte order.
*/
if (tcp->u_arg[4] == SEEK_SET)
tprintf(", %llu, ",
((long long int) tcp->u_arg[1]) << 32 |
((long long) tcp->u_arg[1]) << 32 |
(unsigned long long) (unsigned) tcp->u_arg[2]);
else
tprintf(", %lld, ",
((long long int) tcp->u_arg[1]) << 32 |
((long long) tcp->u_arg[1]) << 32 |
(unsigned long long) (unsigned) tcp->u_arg[2]);
}
else {
long long int off;
long long off;
if (syserror(tcp) || umove(tcp, tcp->u_arg[3], &off) < 0)
tprintf("%#lx, ", tcp->u_arg[3]);
else