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. Fix: Fix provided by Steinar Haugh, sthaug@nethelp.no: See further "Possible bug in freopen()?" thread on hackers@freebsd.org.--u0k6xoLkXPjkJE1lLRQSrzOOxKH8y64KPJNEWs0huHwVGMLR Content-Type: text/plain; name="file.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="file.diff" *** 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); } 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.
>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
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 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.