[net.unix-wizards] a question on open

moi%brandeis.csnet@csnet-relay.arpa (04/13/86)

	The manual page for "open()" mentions that one of the flags one
	can specify with the call is O_APPEND.  It's supposed to request
	that all "write()"s be appended to the end of the file.  Is
	there any reason to use the sequence:
		f = open( file, O_WRONLY );
		lseek( f, 0, L_XTND );
	instead of the single call:
		f = open( file, O_WRONLY | O_APPEND );
	
	I saw the sequence used in a section of code where the single
	call would make sense.
	
						Moises Lejter
						moi%brandeis@csnet-relay

chris@umcp-cs.UUCP (Chris Torek) (04/14/86)

In article <2594@brl-smoke.ARPA> moi%brandeis.csnet@csnet-relay.arpa writes:
>Is there any reason to use the sequence:
>	f = open( file, O_WRONLY );
>	lseek( f, 0, L_XTND );
>instead of the single call:
>	f = open( file, O_WRONLY | O_APPEND );

There are two points to consider here.  First, the latter call does
not work in some Unix variants (notably V6, V7, and 4.1BSD).
Second, the two are not equivalent!  Indeed, this was, as far as
I can tell, the major reason for creating `append mode' in the
first place.  The open/lseek sequence suffers from the `non-atomic
system call' syndrome: multiple writers may well interfere with
each other.  When logging, for example, you are often uninterested
in sequencing, but each new message should be appended to the log
file; in append mode, the kernel guarantees that `simultaneous'
writers will not overwrite each other's messages.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

ark@alice.UUCP (04/14/86)

If you open a file saying O_APPEND, you can only write the
file at the end.  Thus, if you intended later to seek into
the middle somewhere and write, you're out of luck.

rob@ptsfb.UUCP (Rob Bernardo) (04/15/86)

In article <2594@brl-smoke.ARPA> moi%brandeis.csnet@csnet-relay.arpa writes:
>
>	The manual page for "open()" mentions that one of the flags one
>	can specify with the call is O_APPEND.  It's supposed to request
>	that all "write()"s be appended to the end of the file.  Is
>	there any reason to use the sequence:
>		f = open( file, O_WRONLY );
>		lseek( f, 0, L_XTND );
>	instead of the single call:
>		f = open( file, O_WRONLY | O_APPEND );

None that I can think of. You would have to so the lseek() call before every
write() if there might be another process appending to the same file.
And that could fail because between your lseek() and your write()
your process might get swapped out and the other appending process might write
at the end of the file; your write() would then overwrite that of the other
process, rather than be at the end of the file. I've seen this happen
where there was a common error log file for a set of related
programs on a system where the O_APPEND flag was broken causing the implicit
lseek to take place only after the open, but no before each write.

Rob Bernardo, San Ramon, CA    (415) 823-2417    {ihnp4|dual|qantel}!ptsfa!rob
			       Pacific * Bell

paul@whuts.UUCP (HO) (04/16/86)

> 	is there any reason to use the sequence:
> 		f = open( file, O_WRONLY );
> 		lseek( f, 0, L_XTND );
> 	instead of the single call:
> 		f = open( file, O_WRONLY | O_APPEND );
> 	
> 	I saw the sequence used in a section of code where the single
> 	call would make sense.
> 	
I think pre-System III's open has only read, write, and read/write
for open(), and the file descriptor returned is used for lseek.

Starting from System III, open() recognizes more flags.

	Paul Ho

jso@edison.UUCP (John Owens) (04/18/86)

> 	The manual page for "open()" mentions that one of the flags one
> 	can specify with the call is O_APPEND.  [...]  Is
> 	there any reason to use the sequence:
> 		f = open( file, O_WRONLY );
> 		lseek( f, 0, L_XTND );
> 	instead of the single call:
> 		f = open( file, O_WRONLY | O_APPEND );
>
> 						Moises Lejter
> 						moi%brandeis@csnet-relay

Because many versions of UNIX do not support the O_APPEND flag; it's
a fairly recent innovation.  All versions since v7 (at least that I'm
aware of) should support the open/lseek method.


			   John Owens
	    edison!jso%virginia@CSNet-Relay.ARPA
General Electric Company		Phone:	(804) 978-5726
Factory Automation Products Division	Compuserve: 76317,2354
	       houxm!burl!icase!uvacs
...!{	       decvax!mcnc!ncsu!uvacs	}!edison!jso
		 gatech!allegra!uvacs

tim@ism780c.UUCP (04/23/86)

In article <691@edison.UUCP> jso@edison.UUCP (John Owens) writes:
>>      Is there any reason to use the sequence:
>> 		f = open( file, O_WRONLY );
>> 		lseek( f, 0, L_XTND );
>> 	instead of the single call:
>> 		f = open( file, O_WRONLY | O_APPEND );
>
>Because many versions of UNIX do not support the O_APPEND flag; it's
>a fairly recent innovation.  All versions since v7 (at least that I'm
>aware of) should support the open/lseek method.

How about doing both?  Unixes that do not recognize O_APPEND will probably
ignore it, and unixes that do will ignore the lseek.


-- 
Tim Smith       sdcrdcf!ism780c!tim || ima!ism780!tim || ihnp4!cithep!tim

edward@ukecc.UUCP (Edward C. Bennett) (04/27/86)

In article <1968@ism780c.UUCP>, tim@ism780c.UUCP (Tim Smith) writes:
> In article <691@edison.UUCP> jso@edison.UUCP (John Owens) writes:
> >>      Is there any reason to use the sequence:
> >>              f = open( file, O_WRONLY );
> >>              lseek( f, 0, L_XTND );
> >>      instead of the single call:
> >>              f = open( file, O_WRONLY | O_APPEND );
> >
> >Because many versions of UNIX do not support the O_APPEND flag; it's
> >a fairly recent innovation.  All versions since v7 (at least that I'm
> >aware of) should support the open/lseek method.
>
> How about doing both?  Unixes that do not recognize O_APPEND will probably
> ignore it, and unixes that do will ignore the lseek.
>

        #ifdef O_APPEND
                f = open( file, O_WRONLY | O_APPEND );
        #else
                f = open( file, O_WRONLY );
                lseek( f, 0, L_XTND );
        #endif

--
Edward C. Bennett

UUCP: ihnp4!cbosgd!ukma!ukecc!edward

Kentucky: The state that is being dragged, kicking and screaming,
          into the 20th century.

"Goodnight M.A."

allyn@sdcsvax.UUCP (Allyn Fratkin) (04/29/86)

In article <423@ukecc.UUCP>, edward@ukecc.UUCP (Edward C. Bennett) writes:
>
>         #ifdef O_APPEND
>                 f = open( file, O_WRONLY | O_APPEND );
>         #else
>                 f = open( file, O_WRONLY );
>                 lseek( f, 0L, L_XTND );
>         #endif	     ^

In the interests of portability,the 0 should be replaced with 0L in the lseek 
line to make this portable to smaller machines (e.g., machines with
16 bit ints).  Also many machines do not have defines for L_XTND.  
This is the value 2.

-- 
 From the virtual mind of Allyn Fratkin            allyn@sdcsvax.ucsd.edu    or
                          UCSD EMU/Pascal Project  {ucbvax, decvax, ihnp4}
                          U.C. San Diego                         !sdcsvax!allyn

 "Generally you don't see that kind of behavior in a major appliance."

stevesu@copper.UUCP (Steve Summit) (04/30/86)

I hate to post information that has been posted already, but
people keep implying that O_APPEND simply seeks to the end as
the file is opened.  Someone else has already posted an article
pointing this out, but, at least on 4.2bsd,

	f = open(file, O_WRONLY | O_APPEND);

is _n_o_t the same as

	f = open(file, O_WRONLY);
	lseek(f, 0, L_XTND);

If that were all it did, it would not be nearly so useful as what
it does do, which is arrange that a seek to the end of the file
happen immediately before each and every write that you ever do
to the file.  That would seem to be the same as doing

	lseek(f, 0, L_XTND);
	write(f, data, count);

The difference is that the lseek implied by O_APPEND is atomic.
That is, nobody else can do anything to the file between the time
the seek happens and the time the write happens, which would be
possible if you didn't use O_APPEND but instead did the lseek by
hand.

If you know you're the only one writing to the file, O_APPEND
doesn't do you a whole lot of good.  It saves you a bit of system
call overhead, and it makes your program a bit less portable. 
If, on the other hand, you are writing to some kind of a log file
and you know that other processes are too, O_APPEND is
indispensable.

If you use neither O_APPEND nor manual lseeks, you and the other
programs will step all over each other's data (assuming that the
file was opened separately by each process, so each file
descriptor has its own read/write pointer.  If the file was
opened once, and the other processes inherited the same file
descriptor by being forked from the process that opened it, this
case would work).

If you manually seek to the end before each write, you won't step
on the other process's data, or get stepped on yourself, except
when you lose out on race conditions when you get swapped out
after doing the lseek but before doing the write, and one of the
other processes gets swapped in and does a write.  By Murphy's
law, you won't lose on this race condition during your entire
development process, and it will happen for the first time when
your first customer uses your program for the first time.

I don't know how systems other than 4.2bsd interpret O_APPEND.
I would consider systems that implement O_APPEND in the "obvious"
way (by simply seeking to the end as the file is opened, which is
what I used to think O_APPEND did) to be marginally useful, or
downright wrong.

                                         Steve Summit
                                         tektronix!copper!stevesu