App does not use my permissions to create dir

I've written an Switft/macOS App that creates directories deep within its own hierarchy. (no problem). Porting to SwiftUI means these directories and files should go(default) to ~/Documents. Since my Documents dir is (chmod -r 700) the ported app cannot write due to permissions. Which begs he question: what ID does the running app use?
I found:
https://developer.apple.com/forums/thread/82503?answerId=249036022#249036022
and it did change Xcode's :
kMDItemFSOwnerGroupID                   = 20
kMDItemFSOwnerUserID                    = 502
but it still does not write as though it has my permissions.

Aside from changing my ~/Documents dir permissions, how do I make my App (build/run within Xcode) as me so it can write?

Accepted Reply

The App Sandbox has no boxes checks or files selected, on the signing&capabilites for the target.

Those checkboxes and options under App Sandbox are exceptions to the sandbox's restrictions. Since none of those are checked, that means you are running under the highest level of restriction. Your app will not be able to access ~/Documents at all as long as "User Selected File" is still set to "none". If you want to turn off the sandbox, look in the upper, left corner of the App Sandbox area. You will see an "x" button that you can click to turn off the sandbox entirely.

PS: If you want to post code in the future, make sure to use the "Code block" button in the forum toolbar. Otherwise, the forum software will scramble your code. Even so, you should carefully review that code. It looks fragile.


Replies

Since my Documents dir is rwx------ the ported app cannot write due
to permissions.

That’s not the reason. Your app is running as the logged in user and thus it could potentially write to the Documents directory. There are two possible reasons this might be blocked:
  • App Sandbox — Sandboxed processes cannot access arbitrary locations on the file system. Any access beyond their own container must be explicitly granted via some user action (using the open/save panels, drag’n’drop, and so on).

  • Files and Folders privilege — macOS 10.15 and later apply an access control mechanism to certain well-known directories for all apps, sandboxed or not. You can see this in System Preferences > Security & Privacy > Privacy > Files and Folders.

Neither of these are affected by the UI framework that you use for your app (SwiftUI vs AppKit). However, it’s possible that you accidentally enabled the App Sandbox when you created your new SwiftUI project. The sandbox is typically enabled for new projects that you create with Xcode. Oh, and if you’re using Mac Catalyst, such apps are always sandboxed.

As to how you investigate this, I first recommend that you confirm the error in question. If you see EPERM (1) you’re likely hitting one of the access control mechanisms discussed above. Problems with standard file system permissions will usually trigger an EACCES (13) error.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
eskimo, thanks for responding. The App Sandbox has no boxes checks or files selected, on the signing&capabilites for the target.
As for "Files and Folders privilege", Xcode is not granted access to the Documents Folder, but neither can it be. Not for me and not for the administrators login acct.
I found this: apple.stackexchange.com/questions/376907/add-apps-to-files-and-folders-permissions so this may be the problem.

idk where EPERM nor EACCES might be found. They don't appear in the debugging area.

This is my code for saving the file. Should be pretty standard, I see it everywhere.
  1. func saveBAToJSON(fileName: String, object: BinaryAttributes) {

  2.     var dirName = String()

  3.     if flatModel   { dirName += "flatModel"}

  4.     else           { dirName += "needleModel

  5. "}
  6.    

  7.    

  8.    

10.     var ArchiveURL = URL(string: "")
  1.     if PLATFORMMACOS != 0 {  //  BOTH OS's ARE TRUE! Multiplatform project

  2.         let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!

    •        ArchiveURL = URL(string: path)!

    •         .appendingPathComponent("My

  3. Data")
  4.         .appendingPathComponent(dirName, isDirectory: true)

  5.         if !FileManager.default.fileExists(atPath: ArchiveURL!.absoluteString) {

  6.             do { try FileManager.default.createDirectory(atPath: ArchiveURL!.absoluteString, withIntermediateDirectories: true, attributes: nil) }

  7.             catch { print(error) }

20.         }
21.         let extfileName = fileName + "" + dirName
22.         let fileURL = URL(fileURLWithPath: (ArchiveURL!.absoluteString) + extfileName ).appendingPathExtension("json")
23.         do {
24.             let myJSONencoder = JSONEncoder()
25.           myJSONencoder.nonConformingFloatEncodingStrategy = .convertToString(positiveInfinity: "+Infinity", negativeInfinity: "-Infinity", nan: "NaN")  
26.             let data = try myJSONencoder.encode(object)
27.                        try data.write(to: fileURL)
28.         }
29.       catch { print("248 Utility Functions.swift saveToJSON():", error) }
30.     }
31.     if PLATFORM
IOS != 0 {  //  BOTH OS's ARE TRUE! Multiplatform project
32.         ArchiveURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("MyData").appendingPathComponent(dirName, isDirectory: true)
33.         if !FileManager.default.fileExists(atPath: ArchiveURL!.absoluteString) {
34.             do { try FileManager.default.createDirectory(atPath: (ArchiveURL!.absoluteString), withIntermediateDirectories: true, attributes: nil) }
35.             catch { print(error) }
36.         }
37.     }
38.         let extfileName = fileName + "
" + dirName
39.         let fileURL = URL(fileURLWithPath: (ArchiveURL!.absoluteString) + extfileName ).appendingPathExtension("json")
40.         do {
41.             let myJSONencoder = JSONEncoder()
42.             myJSONencoder.nonConformingFloatEncodingStrategy = .convertToString(positiveInfinity: "+Infinity", negativeInfinity: "-Infinity", nan: "NaN")  
43.             let data = try myJSONencoder.encode(object)
44.                        try data.write(to: fileURL)
45.         }
46.         catch { print("265 Utility Functions.swift saveToJSON():", error) }
47. }
48.

Thanks.

The App Sandbox has no boxes checks or files selected, on the signing&capabilites for the target.

Those checkboxes and options under App Sandbox are exceptions to the sandbox's restrictions. Since none of those are checked, that means you are running under the highest level of restriction. Your app will not be able to access ~/Documents at all as long as "User Selected File" is still set to "none". If you want to turn off the sandbox, look in the upper, left corner of the App Sandbox area. You will see an "x" button that you can click to turn off the sandbox entirely.

PS: If you want to post code in the future, make sure to use the "Code block" button in the forum toolbar. Otherwise, the forum software will scramble your code. Even so, you should carefully review that code. It looks fragile.


idk where EPERM nor EACCES might be found. They don't appear in
the debugging area.

Look at the Error value that gets thrown by the failing routine. For Foundation file system errors this is usually a Foundation error but the underlying error will ofter contain the Posix error info. You wan’t see values like EPERM, but rather the number error.

This is my code for saving the file.

Please use a code block (triple backticks) for your code; without that it’s really hard to read )-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
I have discovered an error that functioned in macOS but does not in iOS. Specifically, all the "atPath:" 's above are fed ".absoluteString" which must be ".path" in iOS. Correcting this eliminated the debugger statement:
"Error Domain=NSCocoaErrorDomain Code=642 "You can’t save the file"

Thanks to Leo Dabus Nov 23 '20 at 3:53 @ stackoverflow.com for pointing out the different results of each.