If I have a writable file with an ACL-rule of deny delete
, any [plistableObject writeFoFile:undeletableFile atomically:YES]
call returns NO
, whereas non-atomic writes succeed.
I know, that the atomic write means that a temporary file is written and — if written successfully — eventually renamed. This particular implication of it feels odd, though.
So I wonder, is this due to...
-[NS(Array|Dictionary|Data|String) writeToFile:atomically:]
orThanks in Advance
Daniel
Original question:
I've found this odd behavior the other day on a Mac I restored from a backup:
Most applications were unable to persist their preferences — especially Mail.app which warned with an error message, suggesting that it was unable to write to ~/Library/Preferences
.
Digging deeper, I found that — somehow — most plists had an ACL with the directive group:everyone deny delete
in place; ditching this rule saved the day.
I suspected NSArray|NSDictionary|NSWhatHaveYou
's writeToFile:atomically:
to be responsible* for this behavior and — sure enough — the test-tool I wrote only succeeds when passed NO
as the second argument if the file exists and has such an ACL in place...
(* where by "responsible" I only mean the not-writing-part; the ACL situation was something else entirely)
So I wonder:
Is this a bug or a feature?
While — technically — this method writes a file and upon completion renames it, from a user perspective it is not deleting anything...
If it's a bug:
Should it be filed against NSArray and friends or against the implementation of ACLs?
Any thoughts much appreciated!
Cheers
Daniel
After some digging in the HFS source I've come to the conclusion that there is no such thing as a filesystem-native rename
function in Mac OS.
Instead, it is implemented as (pseudocode)
link!
successful:
return 0
// otherwise
unlink!
successful:
link!
return error_code
// otherwise
return error_code
So this behavior is to be expected :-(
That said, I don't know enough about either filesystems or low-level programming to decide whether the creation of a native rename
would be worth the hassle implementing it.
I strongly feel it would be the right thing to do so, but...
Edit
As jfortman pointed out, an atomic rename would actually be possible and pretty straight-forward through use of the following sequence:
exchangedata( path_to_tempfile, path_to_destination_file, options )
(by the way: the manpage states that this function is around since Darwin 1.3.1/Mac OS X 10.0...)