On Sat, Jun 09, 2012 at 09:06:21PM -0700, Paul Eggert wrote: > Patches for any of these problems would be welcome. > As freadahead seems to be most pressing, it sounds > like that's the best one to work on first. > > > 1. freadahead is inherently non-portable > > That sounds like a challenge! How about using > the following patch? Does it work for you, if > you define SLOW_BUT_NO_HACKS? If so, perhaps > we should just make SLOW_BUT_NO_HACKS the default. > > diff --git a/lib/freadahead.c b/lib/freadahead.c > index 2ba8b34..ad6eb13 100644 > --- a/lib/freadahead.c > +++ b/lib/freadahead.c > @@ -85,7 +85,7 @@ freadahead (FILE *fp) > return 0; > return fp->wp - fp->rp; > #elif defined SLOW_BUT_NO_HACKS /* users can define this */ > - abort (); > + fflush (fp);
Calling fflush on a stream that's reading invokes undefined behavior per ISO C. POSIX defines the behavior for _seekable_ input, but leaves it undefined for non-seekable. (On many systems it purges/discards the unread input, but this is not required, and it's highly undesirable in this usage case anyway.) For seekable input, comparing ftello(f) and the underlying fd offset from lseek(fileno(f),0,SEEK_CUR) would work, but that also will fail for non-seekable input. Here's a sketch of a possible solution, but it's horribly ugly: tmp=dup(fileno(f)); tmp2=socket(AF_UNIX,SOCK_DGRAM,0); /* non-readable */ dup2(tmp2,fileno(f)); close(tmp2); e = ferror(f); c = getc(f); if (!e) clearerr(f); ungetc(c, f); dup2(tmp,fileno(f)); close(tmp); return c>=0; It also may clear the eof flag; not sure how to best fix that yet. While fixing the underlying freadahead function would be nice, it might be better to make sense of WHY it's needed/wanted, if it's even actually useful, and how to avoid the need for it in the first place. Rich