Bug#287824: libc6: fseek() fails and returns -1 without setting errno
According to the man page:
"
RETURN VALUE
The rewind function returns no value. Upon successful
completion,
fgetpos, fseek, fsetpos return 0, and ftell returns the current
offset.
Otherwise, -1 is returned and the global variable errno is set
to indi-
cate the error.
"
I.e. fseek() should return 0 on success or -1 on failure.
You're saying:
"
file->f_pos always
becomes minus values. Return value from lseek() and fseek() functions
are negative, but from POSIX or ANSI point of view, those are
interpreted as error condition.
"
Why would the actual file position affect the return value from
fseek()? Especially without
being a bug (possibly in the man page, but still)?
Regards //Johan
-----Original Message-----
From: GOTO Masanori <gotom@debian.or.jp>
To: Johan Walles <walles@mailblocks.com>; 287824@bugs.debian.org;
debian-kernel@lists.debian.org
Sent: Thu, 13 Jan 2005 21:36:23 +0900
Subject: Re: Bug#287824: libc6: fseek() fails and returns -1 without
setting errno
At Thu, 30 Dec 2004 12:42:18 +0100,
Johan Walles wrote:
The output of the following program is:
johan@foo:~/src/test$ ./a.out
fseek: Unknown error 12345
Since I set errno to 12345 before making the (failing) fseek() call,
fseek() itself apparently fails without setting errno.
Here's the strace output between opening the file and failing:
open("/proc/self/mem", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0) =
0xb7fe8000
_llseek(3, 18446744072635807744, [3526037055030344891], SEEK_SET) =
-1073743872
...
write(4, "fseek: Unknown error 12345\n", 27fseek: Unknown error 12345
) = 27
...
int main(int argc, char *argv[])
{
int variable = 42;
int readvalue = 0;
FILE *mem = fopen("/proc/self/mem", "r");
errno = 12345;
if (fseek(mem, (size_t)&variable, SEEK_SET) != 0) {
perror("fseek");
exit(EXIT_FAILURE);
}
In first, your program has some bugs.
1. Use fseeko instead of fseek.
2. You want to use variable instead of &variable.
3. (size_t) is invalid. When fseeko is used, (off_t) should be used.
4. compile option -D_FILE_OFFSET_BITS=64 helps you for a large file
like /proc/self/mem.
BTW, this issue is very special case. If you pass such &variable ==
0xbffff800, offset of _llseek becomes 18446744072635807744 ==
0xffffffffbffff800. But kernel mem_lseek() in proc.c simply sets
file->f_pos and it does not return any errors when offset is even
(long long)-1 on 32bit architecture. In this case, file->f_pos always
becomes minus values. Return value from lseek() and fseek() functions
are negative, but from POSIX or ANSI point of view, those are
interpreted as error condition.
I think mem_lseek() (thus lseek for /proc/self/mem) is special case
because sometimes memory is existed in all 32 or 64 bit space.
It's not compatible with POSIX's lseek/fseek interface. So I think
even if it shows error, it's not bug of either glibc or kernel.
I send my interpretation to debian-kernel to make sure. Debian-kernel
guys, if you don't agree with my thought, please let me know.
Otherwise, I'll close this bug.
Regards,
-- gotom
----------------------------------------------
Mailblocks - A Better Way to Do Email
http://about.mailblocks.com/info
Reply to: