I'm curious if setvbuf behavior is known to be undefined with regards
to effects it may have on the file pointer. I've found that the
following code works different on AIX 4.3.3 xlc and FreeBSD gcc 2.95.2
19990314 than it does on SCO 5.0.4 cc or Linux gcc egcs-1.1.2 19991024.
This is a bit curious as here's a gcc example that works one way and
one that works the other, and I would think the relevant code is in
libc/glibc.
This is what is going on. If you fopen a file, read a small amount
of data from it and then fseek(fp,0,SEEK_SET), a subsequent setvbuf
to some buffer value (non-0) causes the filepointer returned by
ftell(fp) to be nonzero in the AIX and FreeBSD cases listed above,
and it is zero in the other cases. If you don't do the fread and
fseek first, the filepointer is zero in all cases.
I couldn't find any mention of this behavior, though the particular
conditions here are probably a little unusual. The reason I'm
reading the file first is to check the type of file (by looking at
a header) and decide whether or not to setvbuf based on that.
There are several easy workarounds, I could close and reopen the
file, or simply fseek(fp,0,SEEK_SET) AFTER the setvbuf. But I was
curious as to whether there is any mention anywhere about setvbuf
effect on the filepointer, as I wasn't able to find any...
--
Keith Doyle
ke****@rexx.com
====================== sample code =========================
/*
run the resultant binary with the name of a small file
(a couple hundred bytes long) as a parameter. This program
will fopen the file, read 16 bytes, fseek to 0, then do a
setvbuf with a buffer size of 16384. ftell is then used to
read the filepointer and report its value if it is non zero.
*/
#include <stdio.h>
#include <errno.h>
unsigned char dat[16];
char buf[16394];
int
main(int argc,char **argv)
{
int n,p;
FILE *fp;
if (argv[1][0])
{
fp = fopen(argv[1],"r");
if (!fp)
{
fprintf(stderr,"Can't open %s\n",argv[1]);
exit(1);
}
fread(dat,1,16,fp); /* remove these and they all act the same*/
fseek(fp,0,SEEK_SET);
errno = 0;
n = setvbuf(fp,buf,_IOFBF,16384);
p = ftell(fp);
if (p)
{
printf("setvbuf changed file position to %d\n",p);
}
if (n < 0)
printf("setvbuf returned %d, errno=%d\n",n,errno);
else
printf("setvbuf returned %d\n",n);
exit(0);
} else {
fprintf(stderr,"Usage: bufbug <filename>\n");
exit(1);
}
}
===================end included code========================