“writeToFile:原子地:”使用某些 ACL 处理文件失败
如果我有一个 ACL 规则为 拒绝删除
的可写文件,则任何 [plistableObject writeFoFile:undeletableFileatomically:YES]
调用都会返回 NO
,而非原子写入成功。
我知道,原子写入意味着写入一个临时文件,并且如果写入成功,最终会重命名。不过,它的这种特殊含义感觉很奇怪。
所以我想知道,这是由于......
- HFS+ 中缺乏直接“重命名”,
-[NS(Array|Dictionary|Data|String) writeToFile:atomically:] 实现中存在缺陷
或者- Mac OS X 中 ACL 实施的缺陷?
预先感谢
丹尼尔
原始问题:
前几天我在从备份恢复的 Mac 上发现了这种奇怪的行为:
大多数应用程序无法保留其首选项,尤其是 Mail.app,它会发出错误消息警告,表明它无法写入 ~/Library/Preferences
。
深入挖掘后,我发现,不知何故,大多数 plist 都有一个 ACL,其中包含指令 group:everyone Deny delete
;放弃这条规则挽救了局面。
我怀疑 NSArray|NSDictionary|NSWhatHaveYou
的 writeToFile:atomically:
对这种行为负有责任*,并且——果然——我编写的测试工具只有在通过时才会成功 < code>NO 作为第二个参数,如果文件存在并且具有这样的 ACL...
(* 其中“负责任”我仅指非写入部分;ACL 情况完全是另一回事)
所以我想知道:
这是一个错误还是一个功能?
虽然从技术上讲,此方法会写入一个文件并在完成后对其进行重命名,但从用户的角度来看,它并没有删除任何内容...
如果这是一个错误:
应该针对 NSArray 和其朋友提起诉讼,还是针对 ACL 的实施提起诉讼?
任何想法非常感谢!
干杯
丹尼尔
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...
- lack of a direct 'rename' in HFS+,
- a deficiency in the implementation of
-[NS(Array|Dictionary|Data|String) writeToFile:atomically:]
or - a deficiency in the implementation of ACLs in Mac OS X?
Thanks 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
经过一番挖掘 HFS 源代码我得出的结论是,Mac OS 中不存在文件系统本机
rename
函数。相反,它被实现为(伪代码),
因此这种行为是可以预料的:-(
也就是说,我对文件系统或低级编程了解不够,无法决定是否创建本机重命名
我强烈地觉得这样做是正确的,但是......
编辑
作为jfortman指出,原子重命名实际上是可能的,而且很漂亮通过使用以下序列直接进行:
exchangedata( path_to_tempfile, path_to_destination_file, options )
(顺便说一句:manpage 指出 该函数自 Darwin 1.3.1/Mac OS X 10.0 起就已存在。 .)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)
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...)