Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Any way to allow clobbering empty files when noclobber is set?



Peter Stephenson wrote on Sat, 06 Jun 2020 17:24 +0100:
> On Sat, 2020-06-06 at 08:24 -0700, Bart Schaefer wrote:
> > Just to clarify:  O_CREAT|O_EXCL is actually the NO_clobber-ing open.
> > The clobbering open is just to open it for writing if allowed to. and
> > start scribbling over whatever is there.  
> 
> You're right; in the hypothesised case, the file already exists and
> this pair of options is documented to fail in that case.
> 
> I think the O_TRUNC is therefore the crucial one in our normal clobbering
> open, right?
> 
>     /* If clobbering, just open. */
>     if (isset(CLOBBER) || IS_CLOBBER_REDIR(f->type))
> 	return open(unmeta(f->name),
> 		O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY, 0666);
> 
> We'll truncate at that point, then start writing.  That's the best
> we can do.  If anyone else is also writing to at *at that point*
> --- out of luck, only file locking will help.

In the clobbering open, we use O_CREAT|O_TRUNC, which means: if it
doesn't exist, create it; if it already exists, truncate it.  If some
other process calls open() on the same file immediately after our
open() [or subsequent write()] call returns, there's nothing we can do
about that.

In a regular NO_CLOBBER open, we use O_EXCL, which causes open() to fail
if the file already exists.  In that case, too, if some other process
tries to open the file *without O_EXCL* at any point after our open()
returns successfully, the other process's open() will succeed and may
overwrite our changes, and there's nothing we can do about that.
(On the other hand, if two processes use open(O_EXCL) on the same
filename, at least one of them will get an error.)

As to CLOBBER_EMPTY, the situation is similar.  We can call open() with
O_CREAT but neither O_EXCL nor O_TRUNC and then fstat() the resulting
file.  The same race conditions as in the previous paragraphs exist
here too — for example, someone could open() and write() to the file
after we fstat() it — but we neither can nor need to do any better
about races in this case than in the others.

I agree that we don't want to do file locking here.  Anyone who wants
that can use «zsystem flock».

My point here is really just the one I already made in 45976, and
wasn't answered there: can't we avoid the close()-then-open() sequence
that 45968 does?  That one seems to be an _avoidable_ race condition,
unlike the above ones.

> > Consequently we should be looking at this as an entirely interactive
> > user DWIM feature, and choosing how to implement (or not to) based on
> > that.  
> 
> Yes, I certainly agree with that.
> 
> pws

Cheers,

Daniel



Messages sorted by: Reverse Date, Date, Thread, Author