2011-11-26 72 views
2

我开发的Mac OS X 10.7沙盒应用程序,我想实现文件类似NSDocument的方式节省:非就地保存在OS X沙盒

  1. 重写文件的新内容到一个临时文件
  2. 覆盖原来的文件,临时文件

我遇到的问题是,沙箱否认步骤2中我看到控制台下面一行:

sandboxd: XXXX deny file-write-create /Volumes/Home/sbooth/Test Files/Test

我已经打开此文件进行读取和写入,并且启用了文件系统读取/写入访问权限。我知道NSDocument没有特殊的权利,所以我试图弄清楚我错过了什么。

这里是我现在做的事情(应用程序的这一部分是在C++中,不客观的,C/C++):

FSRef tempFileFSRef; 
if(noErr != FSPathMakeRef((const UInt8 *)tempFileName, &tempFileFSRef, NULL)) 
    ; // Handle it 
CFURLRef destinationDirURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mURL); 
FSRef destinationDirFSRef; 
if(!CFURLGetFSRef(destinationDirURL, &destinationDirFSRef)) 
    ; // Handle it 
CFRelease(destinationDirURL), destinationDirURL = NULL; 
CFStringRef destinationName = CFURLCopyLastPathComponent(mURL); 
FSRef target; 
OSStatus result = FSCopyObjectSync(&tempFileFSRef, &destinationDirFSRef, destinationName, &target, kFSFileOperationOverwrite | kFSFileOperationSkipSourcePermissionErrors); 
if(noErr != result) 
    ; // Handle it 

的代码工作正常,如果我禁用沙盒。

编辑:附加信息是由费米要求。我使用C STDIO打开文件:

FILE *f = fopen(reinterpret_cast<const char *>(buf), "r"); 

,并使用fclose创建临时文件之前关闭。

我的权利是:

<dict> 
    <key>com.apple.security.app-sandbox</key> 
    <true/> 
    <key>com.apple.security.assets.music.read-write</key> 
    <true/> 
    <key>com.apple.security.files.downloads.read-write</key> 
    <true/> 
    <key>com.apple.security.files.user-selected.read-write</key> 
    <true/> 
</dict> 

另外值得一提的是,苹果在他们App Sandbox Design Guide,上面写着:

If you are managing documents using any technology other than the NSDocument class, you must convert to using this class. The NSDocument class automatically works with Powerbox. NSDocument also provides support for keeping documents within your sandbox if the user moves them using Finder.

+0

除了在控制台sandboxd线,是'FSCopyObjectSync'返回一个错误? –

+0

它确实会返回一个错误:-54 | permErr – sbooth

+0

这也并不令人意外,但FSMoveObjectSync表现出相同的行为 – sbooth

回答

0

沙箱只允许读取和应用程序的容器写。如果您启用了读/写权利,那么您只能访问通过OpenSavePanel打开的文件(或者将图标拖动到用户专门打开文件的位置等某种方法)。这将严重限制应用程序如何在文件系统上处理文件。

所以,只要你的应用程序有权对有关文件写的,你可以写你的临时文件到您的应用程序容器,然后检索临时文件内容,然后保存到原来的位置。但是,这假定您的应用程序在整个过程中保持对原始文件的权限。

所以,我的建议是,以确保任何书面文件,你在做应用程序容器完成,然后确认您应用程式仍然有权限调用保存功能之前写入到真正的文件位置。

我最近写了一个类似的问题在我的应用程序失去了那个曾经打开,因为另一个(非沙盒)的应用程序保存到同一个文件中的文件访问。然后,沙箱将该应用程序访问到我的文档,并从应用程序中删除权限。

+0

我可能忽略了一条重要信息:原始文件由用户通过打开对话框选择。使用这种方法,而不是移动临时文件,内容将被复制。这就否定了(我不想用原子这个词)简单地移动文件而不是复制它的好处。 – sbooth

+0

不幸的是,你必须解决沙盒的规则。由于您的代码尝试访问文件系统以外的权限,因此在沙盒权利处于活动状态时这是不可能的。 –

+0

我了解沙箱规则,但我不认为我真的打破了它们。原始文件由用户选择(通过电源箱),临时文件作为对save命令的响应在适当的临时目录中创建。实质上,我试图复制NSDocument的保存行为,而不使用NSDocument,因为我不需要它的全部功能。我认为Yahia在头上碰了一下 - 当我关闭文件时,它可能会从powerbox允许的文件列表中删除。 – sbooth