Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 31 Oct 1998 10:27:06 +0100
From:      sthaug@nethelp.no
To:        Arjan.deVet@adv.iae.nl
Cc:        hackers@FreeBSD.ORG
Subject:   Re: Possible bug in freopen()?
Message-ID:  <17882.909826026@verdi.nethelp.no>
In-Reply-To: Your message of "Fri, 30 Oct 1998 22:39:02 %2B0100 (CET)"
References:  <199810302139.WAA13889@adv.iae.nl>

next in thread | previous in thread | raw e-mail | index | archive | help
> I may have found a bug in freopen() while testing INN 2.2-stable.
> 
> Consider the following program:
> 
>     #include <stdio.h>
>     #include <unistd.h>
> 
>     main () {
> 	FILE *f, *g;
> 	long i;
> 
> 	g = fopen("/tmp/test", "a");
> 	f = freopen("/tmp/test", "a", g);
> 	i = ftell(f);
> 	printf("%d\n", i);
> 	fprintf(f, "test");
> 	i = ftell(f);
> 	printf("%d\n", i);
> 	close(f);
>     }

Your program needs to fclose() the FILE :-)  Aside from that, I believe
you definitely have a point.

The FreeBSD freopen() behavior may actually be correct according to the
standards. My copy of POSIX 1003.1 (First edition, 1990-12-07) says the
following about ftell():


8.2.3.10 ftell()
The underlying function is lseek(). ... If the stream is opened in append
mode or if the O_APPEND flag is set as a consequence of dealing with other
handles on the file, the result of ftell() on that stream is unspecified.


So freopen() behaving differently than fopen() may be allowed by the
standards - but it certainly violates POLA, and probably also the FreeBSD
manual page, which says:

The freopen() function opens the file whose name is the string pointed to
by path and associates the stream pointed to by stream with it.  The
original stream (if it exists) is closed.  The mode argument is used just
as in the fopen() function.

Since it says "just as in the fopen() function", I would expect the effect
on file position to be the same also.

Here is a proposed patch - it simply consists of the relevant part of the
fopen() function, inserted at the appropriate place in freopen().

Steinar Haug, Nethelp consulting, sthaug@nethelp.no
----------------------------------------------------------------------
*** lib/libc/stdio/freopen.c.orig	Tue May 30 07:41:43 1995
--- lib/libc/stdio/freopen.c	Sat Oct 31 10:06:08 1998
***************
*** 151,155 ****
--- 151,166 ----
  	fp->_write = __swrite;
  	fp->_seek = __sseek;
  	fp->_close = __sclose;
+ 
+ 	/*
+ 	 * When opening in append mode, even though we use O_APPEND,
+ 	 * we need to seek to the end so that ftell() gets the right
+ 	 * answer.  If the user then alters the seek pointer, or
+ 	 * the file extends, this will fail, but there is not much
+ 	 * we can do about this.  (We could set __SAPP and check in
+ 	 * fseek and ftell.)
+ 	 */
+ 	if (oflags & O_APPEND)
+ 		(void) __sseek((void *)fp, (fpos_t)0, SEEK_END);
  	return (fp);
  }

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message



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