3

According to Apple's documentation, for an app to access the file system outside of its container, and outside of the directories listed here, it needs to specify a File Access Temporary Exceptions Entitlement.

My app needs to read and write some files in ~/Library/Application Support/, so I set the com.apple.security.temporary-exception.files.home-relative-path.read-write value to /Library/Application Support/ in the app's .entitlement plist.

Now my app is able to read files from ~/Library/Application Support/ if the path is hardcoded like this:

let filePath = URL(fileURLWithPath: "/Users/myUsername/Library/Application Support/path/to/somefile.txt")
let fileContent = try! String(contentsOf: filePath, encoding: .ascii)

However, if I do it like the following, it wouldn't work:

let filePathString = "~/Library/Application Support/path/to/somefile.txt"
let expandedFilePathString = NSString(string: filePathString).expandingTildeInPath
let filePath = URL(fileURLWithPath: expandedFilePathString)
let fileContent = try! String(contentsOf: filePath, encoding: .ascii) // Error

// alternatively
let applicationSupportPath = try! FileManager.default.url(
    for: .applicationSupportDirectory,
    in: .userDomainMask,
    appropriateFor: nil,
    create: false
)
let filePath = applicationSupportPath.appendingPathComponent("path/to/somefile.txt")
let fileContent = try! String(contentsOf: filePath, encoding: .ascii) // Error

Both errors are because the app is trying to access a path in the container: Error Domain=NSCocoaErrorDomain Code=260 "The file “somefile.txt” couldn’t be opened because there is no such file." UserInfo={NSFilePath=/Users/myUsername/Library/Containers/my.bundle.id/Data/Library/Application Support/path/to/somefile.txt, NSUnderlyingError=0x600000c71c20 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}.

In addition, FileManager.default.homeDirectoryForCurrentUser returns /Users/myUsername/Library/Containers/my.bundle.id/Data/.

My question: How do I grant my app access to file system outside of its container, without hard-coding the path?

My previous quesion on the same topic has been marked as a duplicate of this question. However, the "duplicated" question is about hard-coded paths, whereas my question is about non-hard-coded paths. Also, the "duplicated" question is in Objective-C, whereas my question is in Swift.

2 Answers2

3

Giving / to com.apple.security.temporary-exception.files.absolute-path.read-write is what I do for that.

<key>com.apple.security.temporary-exception.files.absolute-path.read-write</key>
    <array>
        <string>/</string>
    </array>

Yes it’s an absolute path but it’s a pretty simple and universal one.

Richard Barber
  • 5,257
  • 2
  • 15
  • 26
  • Thank you. I just tried it in my code, but it didn't work for me. Is adding `com.apple.security.temporary-exception.files.absolute-path.read-write` to the entitlement plist the only thing you did to make it work for you? – Wowbagger and his liquid lunch Feb 19 '20 at 02:28
  • Yes along with the array containing the string. – Richard Barber Feb 19 '20 at 05:05
  • Also if you are only trying to get into `~/Library` without knowing the absolute path you may do that in programming by taking the returned intra-container data path the runtime sees as HOME and slide the terminator over from the end to get rid of the suffix. Of course taking care with unintended truncation. – Richard Barber Feb 19 '20 at 05:14
  • https://github.com/Beep6581/RawTherapee/blob/85bffa10381450bee541283616e3572665f12314/rtgui/options.cc#L2273-L2281 – Richard Barber Feb 19 '20 at 05:36
  • @RichardBarber : Did you find out, how to access files outside the container? I added "com.apple.security.temporary-exception.files.absolute-path.read-write" along with the array containing the path in the entitlement file. It does not work - is there anything else to do? – mica Jan 02 '21 at 17:40
  • 1
    @mica Nope, I believe this ability requires codesign entitlement within the typical secured runtime environment. – Richard Barber Jan 03 '21 at 14:59
-1

I had a similar issue. I would access to outside of container's folder. this is help to me

let applicationSupportFolder = "/Users/\(NSUserName())/Library/Application Support"
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 10 '21 at 07:48