When to use fflush()?

Steve Summit scs at hstbme.mit.edu
Sun Sep 17 06:35:28 AEST 1989


In article <14507 at haddock.ima.isc.com> karl at haddock.ima.isc.com (Karl Heuer) writes:
>I've forgotten whether this issue was ever resolved: what should happen if the
>output stream is a VMS record-oriented file?  If the currently buffered output
>contains no newlines, is it appropriate for fflush() to do nothing, and return
>success?

In article <10913 at smoke.BRL.MIL> gwyn at brl.arpa (Doug Gwyn) writes:
>The specification says that unwritten data IS delivered to the host
>environment.  It does not (and cannot) be specific about how that is
>actually accomplished.
>I would think that so long as the implementation ensures that the
>data will reach the record-structured file SOMEtime, that would
>suffice.

Before the distinction between pANS C and Posix was as clear as
it is today, and before the exhortation to use stdio rather than
system calls in portable code was as strong, it was common to
provide open/read/write/etc. in a "foreign" (non-Unix) C RTL.  In
that case, the right place to handle newline-to-record-structure
conversion is of course in the write(2) emulation, not in stdio.
Indeed, using a VMS C RTL I once wrote, the stdio sources could
be taken from a Unix machine and compiled, without essential
change, to run successfully "on top of" the Unix system call
emulation.

In this situation, the mind-set when considering the stdio code
is that the underlying open/read/write emulation is "the
operating system" even though it is actually library code running
in user mode.  fflush's job is done when it has called write().
(The data has been "delivered to the host environment.")  The
fact that the characters which have been written are waiting in a
buffer at the write() level (waiting for the line to be
terminated or the file closed) and have not, in fact, been
written to the disk, is fairly equivalent to the fact that Unix
uses delayed writes and the same thing is essentially true after
a write(2) there.  (The buffering is merely happening one level
further up, or two levels if you consider that an emulation on
VMS is properly written on top of RMS which may impose its own
level of buffering before the VMS equivalent of low-level I/O
system calls are reached.)

A more interesting question (under this scheme) would be what
should happen if fflush() (or any code, for that matter) were to
call fsync() for a record-oriented text file.  I don't remember
if I implemented fsync() and, if I did, if I asked or answered
the premature record termination question.  A quality emulation
of fsync semantics would certainly force data to be written as
close to the disk as possible (calling RMS and lower-level flush
operations as appropriate).  It is probably possible to extend
records in-place, as long as they're at the end of the file, so
the premature record terminator might be "erased" if later I/O,
after the fflush(), were to complete the "line" and add an
explicit \n.  It would require some fairly ugly state variables
in the emulation's "file descriptor," of questionable payoff.

(DEC's VMS C RTL uses by default a previously-unimportant VMS
file type called "stream LF", rather than the standard
record-oriented carriage-control text files, to circumvent these
kinds of difficulties.  Unfortunately, other VMS utilities
historically had only sporadic understanding of stream-LF files,
to the point that the first versions of DEC's VMS C compiler
failed Ritchie's generality/usefulness test: C program text
output from a C program was not acceptable as input to the C
compiler.  C's growing popularity has forced DEC to expand the
handling of stream-LF files elsewhere in VMS, including, you'll
be relieved to know, the input section of the C compiler.)



More information about the Comp.lang.c mailing list