Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the /private prefix on an iOS file path indicate?

I have a bug when my app runs on the iPhone but not when it runs on the simulator. I was using the length of the home directory path to extract the relative path of a file in /Documents. Unfortunately this doesn't always work correctly on the iPhone because the prefix "/private" is being added to the home path. However, with or without the prefix, the same file is referenced ok. The following code demonstrates this inconsistency. What is the purpose of "/private" and when is it supplied by iOS?

- (IBAction)testHomepath:(id)sender {     NSFileManager *fmgr = [NSFileManager defaultManager];     NSString  *homePath = [NSString stringWithFormat:@"%@/Documents",NSHomeDirectory()];     NSString  *dirPath  = [homePath stringByAppendingPathComponent:@"TempDir"];     NSURL     *dirURL   = [NSURL fileURLWithPath:dirPath];     NSString  *filePath = [dirPath  stringByAppendingPathComponent:@"test.jpg"];     [fmgr createDirectoryAtPath:dirPath withIntermediateDirectories:NO attributes:nil error:nil];     [fmgr createFileAtPath:filePath contents:nil attributes:nil];     NSArray *keys  = [[NSArray alloc] initWithObjects:NSURLNameKey,nil];     NSArray *files = [fmgr contentsOfDirectoryAtURL:dirURL includingPropertiesForKeys:keys options:0 error:nil];     NSURL *f1 = (files.count>0)? [files objectAtIndex:0] : 0;     NSURL *f2 = (files.count>1)? [files objectAtIndex:1] : 0;     bool   b0 = [fmgr fileExistsAtPath:filePath];     bool   b1 = [fmgr fileExistsAtPath:f1.path];     bool   b2 = [fmgr fileExistsAtPath:f2.path];      NSLog(@"File exists=%d at path:%@",b0,filePath);     NSLog(@"File exists=%d at path:%@",b1,f1.path);     NSLog(@"File exists=%d at path:%@",b2,f2.path); } 

The following is written to the log when running on the iPhone. I manually spaced the output to show the difference between lines 1 and 2.

2013-02-20 16:31:26.615 Test1[4059:907] File exists=1 at path:        /var/mobile/Applications/558B5D82-ACEB-457D-8A70-E6E00DB3A484/Documents/TempDir/test.jpg 2013-02-20 16:31:26.622 Test1[4059:907] File exists=1 at path:/private/var/mobile/Applications/558B5D82-ACEB-457D-8A70-E6E00DB3A484/Documents/TempDir/test.jpg 2013-02-20 16:31:26.628 Test1[4059:907] File exists=0 at path:(null) 

The following is written to the log when running on the simulator (no "/private"):

2013-02-20 16:50:38.730 Test1[7224:c07] File exists=1 at path:/Users/kenm/Library/Application Support/iPhone Simulator/6.1/Applications/C6FDE177-958C-4BF5-8770-A4D3FBD281F1/Documents/TempDir/test.jpg 2013-02-20 16:50:38.732 Test1[7224:c07] File exists=1 at path:/Users/kenm/Library/Application Support/iPhone Simulator/6.1/Applications/C6FDE177-958C-4BF5-8770-A4D3FBD281F1/Documents/TempDir/.DS_Store 2013-02-20 16:50:38.733 Test1[7224:c07] File exists=1 at path:/Users/kenm/Library/Application Support/iPhone Simulator/6.1/Applications/C6FDE177-958C-4BF5-8770-A4D3FBD281F1/Documents/TempDir/test.jpg 
like image 220
KenM Avatar asked Feb 21 '13 00:02

KenM


People also ask

How do I see file path on iPhone?

Launch the native Files app on your iPhone or iPad. Make sure you're in the “Browse” section and select the location where your file is stored. Next, head over to the directory where the file is located and simply long-press on the file to access more options. Now, select “Info” to view all the information on the file.

How do I open a file path in Swift?

open("path"); while var line = fh. readline() { ... }; fh. close() . @BryanChen Yep, that's my hope.


1 Answers

I tried this from the debugger and discovered that URLByResolvingSymlinksInPath "fixes" the /private/ addition.

(lldb) p (NSURL *)[NSURL fileURLWithPath:@"/private/var" isDirectory:YES] (NSURL *) $1 = 0x1fd9fc20 @"file://localhost/private/var/" (lldb) po [$1 URLByResolvingSymlinksInPath] $2 = 0x1fda0190 file://localhost/var/  (lldb) p (NSURL *)[NSURL fileURLWithPath:@"/var" isDirectory:YES] (NSURL *) $7 = 0x1fd9fee0 @"file://localhost/var/" (lldb) po [$7 URLByResolvingSymlinksInPath] $8 = 0x1fda2f50 file://localhost/var/ 

as you can see, file://localhost/var is what we really want here.

Because of this, it seemed obvious that /private/var is a symlink to /var. However, @Kevin-Ballard points out that is not true. I confirmed that he is correct, and /var is the symlink to /private/var (sigh)

(lldb) p (NSDictionary *)[[NSFileManager defaultManager] attributesOfItemAtPath:@"/var" error:nil] (NSDictionary *) $3 = 0x1fda11b0 13 key/value pairs (lldb) po $3 $3 = 0x1fda11b0 {     ...     NSFileType = NSFileTypeSymbolicLink; }  (lldb) p (NSDictionary *)[[NSFileManager defaultManager]   attributesOfItemAtPath:@"/private/var" error:nil] (NSDictionary *) $5 = 0x1fda4820 14 key/value pairs (lldb) po $5 $5 = 0x1fda4820 {     ...     NSFileType = NSFileTypeDirectory; } 

So URLByResolvingSymlinksInPath is doing something funny here, but now we know. For this particular problem, URLByResolvingSymlinksInPath still sounds like a good solution that works for both the simulator and the device and should continue to work in the future if something changes.

like image 56
Skotch Avatar answered Sep 25 '22 06:09

Skotch