2011-11-26 90 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