Article View: comp.std.c
Article #87Re: does "always append" apply to "a+" mode?
From: Clive Feather
Date: Wed, 05 Aug 1992 08:12
Date: Wed, 05 Aug 1992 08:12
120 lines
6545 bytes
6545 bytes
In article <13905@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
>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.
>> 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."
I looked this up, and here is what I found.
The original quotation is slightly wrong: it (section 7.9.5.3 "fopen")
actually 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
| lseek function.
I then went to the introduction to the section, which in this case is
7.9.3 "Files" (looking at the introduction of a section is *always* a
good idea). This defines buffering:
| When a stream is unbuffered, characters are intended to appear from
| the source or at the destination as soon as possible. Otherwise
| characters may be accumulated and transmitted to or from the host
| environment as a block.
[...]
| Support for these characteristics is implementation-defined, and may
| be affected by the setbuf and setvbuf functions.
I read this as meaning that they know the desirable model, but realize
there are perverse systems that can't support it.
Just before this text, still in 7.9.3, is the words:
| all output takes place as if characters were written by successive
| calls to the fputc function.
So, we go to section 7.9.7.3 ("fputc"). This reads:
| If the file cannot support positioning requests, or the stream was
| opened with append mode, the character is appended to the output
| stream.
Note that it is the stream that is written to, not the file.
I read all this as having the following meaning for append streams:
- If the file is unbuffered, then each character should be[*] appended
atomically to the file. Multiple characters from a single fprintf or
fwrite operation may be interleaved with those from another process.
- If the file is buffered, then each character is appended to the stream
buffer in turn. When the buffer is flushed (when it is full, or when a
newline is written to a line-buffered stream), which can happen in the
middle of a single fprintf of fwrite, the buffer should be[*]
atomically appended to the file. Note that an fprintf or fwrite could
be split, and interleaved, in this case.
[*] "should be" means that if the underlying system provides such a
feature, it ought to be used, but the Standard writers knew there were
systems that did not, and so didn't make promises they can't keep. They
do, however, require the implementer to document how they handle this.
> 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.
Hmm. I see an ambiguity in the standard, but not for this reason. For an
append stream, fputc writes the character to the end of the stream, and
"advances the indicator appropriately". To me, this means that:
- EITHER the indicator is incremented,
- OR it is set to the new EOF,
and the implementation does *not* have to document its choice. Note that
if the indicator is currently at EOF, then these two are the same, so
once the indicator is at EOF, it will remain there.
> 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?
The Standard does not specify why ftell can fail, just that it can, so I
presume this is OK.
> 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_.
The Standard recommends that you write the record into a buffer
(ensuring it is less than one buffer-full), and then flush the buffer
with fflush. The maximum size of buffer for which this will work is not
specified, but I would be extremely surprised if it is less than BUFSIZ.
If this won't work, the implementation's documentation will say so, and
there probably won't be *any* way to do it (or the implementation would
have done it that way in the first place).
--
Clive D.W. Feather | IXI Limited | If you lie to the compiler,
clive@x.co.uk | 62-74 Burleigh St. | it will get its revenge.
Phone: +44 223 462 131 | Cambridge CB1 1OJ | - Henry Spencer
Fax: +44 223 462 132 | United Kingdom |
Technical Details
Message-ID:
<1992Aug05.081224.17647@x.co.uk>Path:
arc1-ca.pugleaf.net!sparky!uunet!mcsun!uknet!acorn!ixi!cliveReferences:
<13851@goanna.cs.rmit.oz.au> <15cajaINNrum@early-bird.think.com> <13905@goanna.cs.rmit.oz.au>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!mcsun!uknet!acorn!ixi!clive From: clive@x.co.uk (Clive Feather) Newsgroups: comp.std.c Subject: Re: does "always append" apply to "a+" mode? Message-ID: <1992Aug05.081224.17647@x.co.uk> Date: 5 Aug 92 08:12:24 GMT References: <13851@goanna.cs.rmit.oz.au> <15cajaINNrum@early-bird.think.com> <13905@goanna.cs.rmit.oz.au> Organization: IXI Limited, Cambridge, UK Lines: 120