From nobody  Sat Oct 31 05:14:38 1998
Received: (from nobody@localhost)
          by hub.freebsd.org (8.8.8/8.8.8) id FAA22690;
          Sat, 31 Oct 1998 05:14:38 -0800 (PST)
          (envelope-from nobody)
Message-Id: <199810311314.FAA22690@hub.freebsd.org>
Date: Sat, 31 Oct 1998 05:14:38 -0800 (PST)
From: Arjan.deVet@adv.iae.nl
To: freebsd-gnats-submit@freebsd.org
Subject: freopen() in append mode followed by ftell() gives strange results
X-Send-Pr-Version: www-1.0

>Number:         8518
>Category:       bin
>Synopsis:       freopen() in append mode followed by ftell() gives strange results
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Oct 31 05:20:00 PST 1998
>Closed-Date:    Tue Jun 5 10:57:12 PDT 2001
>Last-Modified:  Tue Jun 05 11:00:18 PDT 2001
>Originator:     Arjan de Vet
>Release:        FreeBSD 2.2.7
>Organization:
>Environment:
FreeBSD adv.iae.nl 2.2.7-RELEASE FreeBSD 2.2.7-RELEASE #0: Mon Jul 27 20:40:41 CEST 1998     root@adv.iae.nl:/usr/src/sys/compile/ADV  i386
>Description:
During testing INN 2.2beta I discovered a possible 'bug' in the
freopen() call when used with "a" (append mode). The first ftell()
call always give 0 (irrespective of the current file length) and
subsequent writes to the file ftell() does not tell the current
write position in the file but the number of bytes written.

>How-To-Repeat:
#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);
    fclose(f);
}

Create empty /tmp/test file and run the program three times. Each
time it will print 0 and 4. BSD/OS prints 0 4, 0 8 and 0 12. Solaris
and Linux print 0 4, 4 8 and 8 12.

>Fix:
Fix provided by Steinar Haugh, 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);
  }

See further "Possible bug in freopen()?" thread on hackers@freebsd.org.

>Release-Note:
>Audit-Trail:

From: Bruce Evans <bde@zeta.org.au>
To: Arjan.deVet@adv.iae.nl, freebsd-gnats-submit@FreeBSD.ORG
Cc: sthaug@nethelp.no
Subject: Re: bin/8518: freopen() in append mode followed by ftell() gives strange results
Date: Tue, 10 Nov 1998 19:25:11 +1100

 >During testing INN 2.2beta I discovered a possible 'bug' in the
 >freopen() call when used with "a" (append mode). The first ftell()
 >call always give 0 (irrespective of the current file length) and
 >subsequent writes to the file ftell() does not tell the current
 >write position in the file but the number of bytes written.
 
 This seems to be only a ``bug''.  POSIX.1-1990 says:
 
 "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".
 
 >>How-To-Repeat:
 >#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);
 >    fclose(f);
 >}
 >
 >Create empty /tmp/test file and run the program three times. Each
 >time it will print 0 and 4. BSD/OS prints 0 4, 0 8 and 0 12. Solaris
 >and Linux print 0 4, 4 8 and 8 12.
 
 The BSD/OS behaviour is the least surprising.  The initial offsets
 of zero may even be required (if no other process writes to the file).
 POSIX.1 specifies fopen() to just use open(), and freopen() to do much
 the same thing as fopen().  Therefore, the initial offsets at the file
 descriptor level are zero, and for "a+" mode, an initial read would
 start at the beginning of the file.  Only the fuzzy specification of
 permits the initial offsets at the stream level to be nonzero.
 
 Bruce

From: Arjan de Vet <Arjan.deVet@adv.iae.nl>
To: bde@zeta.org.au (Bruce Evans)
Cc: Arjan.deVet@adv.iae.nl, freebsd-gnats-submit@FreeBSD.ORG,
        sthaug@nethelp.no
Subject: Re: bin/8518: freopen() in append mode followed by ftell() gives strange results
Date: Sun, 15 Nov 1998 15:03:00 +0100 (CET)

 Bruce Evans:
 
 >>Create empty /tmp/test file and run the program three times. Each
 >>time it will print 0 and 4. BSD/OS prints 0 4, 0 8 and 0 12. Solaris
 >>and Linux print 0 4, 4 8 and 8 12.
 >
 >The BSD/OS behaviour is the least surprising.  The initial offsets
 >of zero may even be required (if no other process writes to the file).
 >POSIX.1 specifies fopen() to just use open(), and freopen() to do much
 >the same thing as fopen().  Therefore, the initial offsets at the file
 >descriptor level are zero, and for "a+" mode, an initial read would
 >start at the beginning of the file.  Only the fuzzy specification of
 >permits the initial offsets at the stream level to be nonzero.
 
 But let's not look at the initial offset now but the offsets after writing 4
 bytes. FreeBSD reports here three times '4' which looks completely wrong in
 my opinion: when you have "testtest" in a file and you append "test" ftell
 should say 12 isn't it?
 
 Arjan
 
 -- 
 Arjan de Vet, Eindhoven, The Netherlands              <Arjan.deVet@adv.iae.nl>
 URL: http://www.iae.nl/users/devet/           for PGP key: finger devet@iae.nl
State-Changed-From-To: open->closed 
State-Changed-By: phk 
State-Changed-When: Tue Jun 5 10:57:12 PDT 2001 
State-Changed-Why:  
You can never trust *seek() to tell you where the next write 
will happen on a file opened in append mode, because another 
process might sneak in between your *seek() and write() calls. 

One could possibly use *seek() to discover the offset after the 
write completes and set the offset, it would then be possible to 
retroactively compute the location of the data in the file by 
calling write() first and then *seek(), subtracting the number of 
bytes written. 


http://www.FreeBSD.org/cgi/query-pr.cgi?pr=8518 
>Unformatted:
