Search code examples
cocoansfilemanager

Enumerating over a directory gives me an error when I try to follow aliases


I want my users to be able to drop a folder into my OSX app. I then look at all the files in the directory and its subdirectories. That works fine but not when there is an alias in the directory. The alias is resolved correctly (Thanks to Matt Gallagher, shame on you Apple) but the enumerator does not allow me to do enumerate the target directory (it just returns no elements and the error below). Here is some sample code:

-(void)enumDirAtPath:(NSString*)path  {
    NSString* file_enum = nil;
    NSDirectoryEnumerator* enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path];
    while (file_enum = [enumerator nextObject])
    {
        NSString* file =  [[NSString stringWithFormat:@"%@/%@",path,file_enum] stringByResolvingSymlinksAndAliases];

        BOOL isDirectory = NO;
        [[NSFileManager defaultManager] fileExistsAtPath:file isDirectory: &isDirectory];
        if (!isDirectory) {
            NSLog(@"Adding file: %@",file);
        } else {
            NSLog(@"Found dir: %@",file);
           [self enumDirAtPath: file];
        }
   }
}

the same code with enumeratorAtURL:includingPropertiesForKeys:options:errorHandler: gives me this error:

error: Error Domain=NSCocoaErrorDomain Code=257 "The file “Musik” couldn’t be opened because you don’t have permission to view it." UserInfo=0x1094cf670 {NSURL=file://localhost/Users/david/Desktop/Musik, NSFilePath=/Users/david/Desktop/Musik, NSUnderlyingError=0x1094d43f0 "The operation couldn’t be completed. Operation not permitted"}

Even If I just dispatch_async the recursive call it won't let me do it. Is there any way I can just iterate over a directory and get all the content?

Note: I am fully aware that this could result in infinite loops. This code is just to illustrate the problem.


Solution

  • I‘m pretty damn sure the answer is right there in the error message:

    The file “Musik” couldn’t be opened because you don’t have permission to view it.

    Reveal the destination of the alias in the Finder application and check its permission via “Get Info” or ls -l@ in the Terminal — I’d bet that your user account david is not being granted one of the following permissions:

    • read
    • execute
    • list

    The last one will typically not be visible on the command line except in combination with an explicit deny-access-control-entry.