[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: