2

我正在为 Mac OS X 10.7 开发一个沙盒应用程序,我正在尝试以类似于以下方式实现文件保存NSDocument

  1. 将文件的新内容重写为临时文件
  2. 用临时文件覆盖原始文件

我遇到的问题是沙箱拒绝第 2 步。我在控制台中看到以下行:

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

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

这是我现在的工作方式(应用程序的这一部分是 C++,而不是 Objective-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

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

编辑:Femi 要求提供更多信息。我使用 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>

还值得注意的是,Apple 在他们的App Sandbox Design Guide中说:

如果您使用 NSDocument 类以外的任何技术管理文档,则必须转换为使用此类。NSDocument 类自动与 Powerbox 一起使用。如果用户使用 Finder 移动文档,NSDocument 还支持将文档保存在沙箱中。

4

1 回答 1

0

沙盒仅允许您从应用程序的容器中读取和写入。如果您启用了读/写权利,那么您只能访问通过 OpenSavePanel 打开的文件(或某些方法,例如将图标拖到用户专门打开文件的停靠栏)。这将严重限制应用程序如何处理文件系统上的文件。

因此,只要您的应用程序有权改写相关文档,您就可以将临时文件写入应用程序容器,然后检索临时文件内容,然后保存到原始位置。但是,这假设您的应用程序在整个过程中维护对原始文件的权限。

因此,我的建议是确保您所做的任何写入都在应用程序容器中完成,然后在调用保存函数之前验证您的应用程序仍然有权写入真实文件位置。

我最近写了一个类似的问题,我的应用程序无法访问已打开的文件,因为另一个(非沙盒)应用程序保存到同一个文件中。然后沙盒授予该应用访问我的文档的权限,并从该应用中删除了权限。

于 2012-01-14T18:46:46.050 回答