Article View: comp.std.c
Article #84Re: does "always append" apply to "a+" mode?
From: Richard A. O'Keefe
Date: Tue, 04 Aug 1992 02:08
Date: Tue, 04 Aug 1992 02:08
89 lines
5516 bytes
5516 bytes
In article <15cajaINNrum@early-bird.think.com>, barmar@think.com (Barry Margolin) writes:
> In article <13851@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
> [In some other article, whose attribution is gone, someone wrote:]
> >> In the section on fopen (4.9.5.3, pp. 130--131), the Standard says:
> >> Opening a file with append mode (|'a'| as the first character in
> >> the |mode| argument) causes all subsequent writes to the file to be
> >> forced to the then current end-of-file, regardless of intervening
> >> calls to the |fseek| function. ...
>
> >It has never been clear to me what the model is for "a" mode.
> >Is it like Fortran's
> > OPEN(UNIT=..., FILE='name', ACTION='WRITE', POSITION='APPEND')
> >(i.e. is it just like "w" mode except for being _initially_ positioned at
> >the end of the existing file), or is like like UNIX's
> > open("name", O_WRONLY|O_APPEND|O_CREAT)
>
> From the section of the standard that the original poster copied above, it
> seems pretty clear that the intent is to be like O_APPEND. It specifically
> says, "the then current end-of-file", which I believe means "the
> end-of-file at the time of any given write".
Well, I asked because it is _not_ pretty clear to me. If they meant "the
end-of-file at the time of any given write" they should have written something
like
"If a file is opened with append mode ... then every subsequent
write is forced to the end of file current at the time of the write,
regardless of intervening calls to the fseek function."
and for maximum clarity they could have said something about
... forced to the end of file as defined by the external file object
at the time of the write ...
I had indeed forgotten about the possibility that the operating system might
not be able to write one's record atomically.
We are left with something where something _important_ happens whenever a
"write to the file" occurs, but where we have no way of ensuring that writes
happen exactly when we want them (we can _force_ a write to occur by using
fflush(), but we cannot _prevent_ a write occurring whenever stdio sees fit)
and where we have no way of _finding out_ when a write occurs. A definition
in terms of unobservable and uncontrollable events doesn't help much.
I can't for the life of me figure out how to define ftell() for an "a" mode
file, nor for an "a+" mode file except during periods of reading. This is
in large part because I never did manage to figure out any way to determine
where a record written atomically to an O_APPEND UNIX file went. It is not
completely clear to me that one can rely on lseek() even when it makes sense,
and O_APPEND makes sense for some devices that do not support lseek(). I've
check Chris Torek's stdio implementation (I know it's not the standard, but
it _is_ thorough) and in the case of an "a" mode file, fseek() returns
lseek() "where the last write ended?" + number-of-buffered-bytes, and that
is a useful thing to know _only_ when this is the only process extending
the file, and in that case the Fortran approach would work just fine.
Considering MS-DOS, the nearest that I can figure out using the information
in "The MS-DOS ENcyclopedia" is to use the equivalent of lseek() followed
by write(), which isn't quite right. If one wants to be absolutely perfect
about writing at the end-of-file position current at the exact time of the
write, then you'd have to lock the file, seek, write, and then unlock. That's
a lot of overhead. This is the kind of thing which makes me wonder just how
seriously the unclear wording is to be taken.
One anomaly in Torek's stdio is that if you open a binary file for output,
it still relies on lseek() to find out where it is, even though this can
be determined entirely from the sequence of calls to stdio functions. So
FILE *f;
long p;
f = fopen(FileName, "wb");
assert(f != NULL);
p = ftell(f);
assert(p != -1);
can fail in the second assert(), even though the position _must_ be 0. I
understand why it is done this way, and don't really mind, but is this ok?
[Look, I _want_ to RTFS, but I put in a request for a copy of the FS nearly
a year ago, and it _still_ hasn't arrived in the library.] My preference
would be to maintain the position entirely by counting operations, and only
to use lseek() [or, in Torek's package, the user's seek() function] only
when an fseek() occurs. I know this wouldn't give useful results for "a"
mode files, but neither does the present scheme, and that's what I'm trying
to understand.
I suppose this is really material for alt.lang.cfutures, but I would find
a mode ("e", perhaps?) which combines opening an existing file at the end
with the predictability of "w" mode (like FORTRAN POSITION='APPEND', in
fact) rather more useful than "a". If I want to _reliably_ append records
atomically to the end of a log file, it looks as though I have to use
OS-dependent code _anyway_.
--
You can lie with statistics ... but not to a statistician.
Technical Details
Message-ID:
<13905@goanna.cs.rmit.oz.au>Path:
arc1-ca.pugleaf.net!sparky!uunet!munnari.oz.au!goanna!okReferences:
<24992@dog.ee.lbl.gov> <13851@goanna.cs.rmit.oz.au> <15cajaINNrum@early-bird.think.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!munnari.oz.au!goanna!ok From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) Newsgroups: comp.std.c Subject: Re: does "always append" apply to "a+" mode? Message-ID: <13905@goanna.cs.rmit.oz.au> Date: 4 Aug 92 02:08:20 GMT References: <24992@dog.ee.lbl.gov> <13851@goanna.cs.rmit.oz.au> <15cajaINNrum@early-bird.think.com> Organization: Comp Sci, RMIT, Melbourne, Australia Lines: 89