Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Oct 2006 17:30:22 GMT
From:      Ruslan Ermilov <ru@FreeBSD.org>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: bin/104295: freopen(NULL, ...) does bad things to file offset.
Message-ID:  <200610111730.k9BHUMH4085536@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/104295; it has been noted by GNATS.

From: Ruslan Ermilov <ru@FreeBSD.org>
To: trasz <trasz@pin.if.uz.zgora.p>
Cc: bug-followup@FreeBSD.org, Andrey Chernov <ache@nagual.pp.ru>
Subject: Re: bin/104295: freopen(NULL, ...) does bad things to file offset.
Date: Wed, 11 Oct 2006 21:14:44 +0400

 On Wed, Oct 11, 2006 at 01:02:28PM +0000, trasz wrote:
 > Freopen(3) does bad things to the file offset when supplied with NULL
 > as a file path (freopen(NULL, mode, fd);).  The test program below returns:
 > 
 > file offset before freopen is 100.
 > file offset after freopen is 2399.
 > 
 It's actually the minimum of a pagesize and file size.  Now we know
 the size of your /etc/passwd.  :-)
 
 > #include <stdio.h>
 > 
 > int main(void)
 > {
 >         int ret;
 >         FILE *f;
 > 
 >         f=fopen("/etc/passwd", "r");
 >         if (f==NULL) {
 >                 perror("fopen");
 >                 exit(-1);
 >         }
 > 
 >         ret=fseek(f, 100, SEEK_CUR);
 >         if (ret<0) {
 >                 perror("fseek");    
 >                 exit(-1);
 >         }
 > 
 >         ret=ftell(f);
 >         fprintf(stderr, "file offset before freopen is %d.\n", ret);
 > 
 >         f=freopen(NULL, "r", f);
 >         if (f==NULL) {
 >                 perror("freopen");
 >                 exit(-1);
 >         }
 > 
 >         ret=ftell(f);
 >         fprintf(stderr, "file offset after freopen is %d.\n", ret);
 > 
 >         return 0;
 > }
 > 
 It's only a problem when a file was initially opened read-only;
 if you open it "r+" the problem doesn't show up.
 
 I don't know the stdio code very well, but I tracked it down to
 optimizations in _fseeko(); basically, freopen() calls
 _fseeko(fp, 0, SEEK_SET, 0) and that's getting optimized by not
 doing a real seek and simply adjusting the pointers.  Later in
 freopen(), these pointers get reset but the underlying file in
 question stays at its old position.  I've worked around this
 by temporarily disabling the fseek() optimization:
 
 %%%
 Index: freopen.c
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/stdio/freopen.c,v
 retrieving revision 1.13
 diff -u -p -r1.13 freopen.c
 --- freopen.c	22 May 2004 15:19:41 -0000	1.13
 +++ freopen.c	11 Oct 2006 17:01:00 -0000
 @@ -115,6 +115,7 @@ freopen(file, mode, fp)
  		}
  		if (oflags & O_TRUNC)
  			ftruncate(fp->_file, 0);
 +		fp->_flags |= __SNPT;
  		if (_fseeko(fp, 0, oflags & O_APPEND ? SEEK_END : SEEK_SET,
  		    0) < 0 && errno != ESPIPE) {
  			sverrno = errno;
 %%%
 
 Someone with more stdio-fu should pick it up.  Andrey?
 
 
 Cheers,
 -- 
 Ruslan Ermilov
 ru@FreeBSD.org
 FreeBSD committer



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200610111730.k9BHUMH4085536>