Full URL from FSCopyURLForVolume

2019-09-05 01:18发布

问题:

I am running into an issue getting the full url for a file with FSCopyURLForVolume. I am using the code from this issue Determine AFP share from a file URL but it isn't giving me the full url. For example:

With a path like: /Volume/server/html/index.html

All I get back is url to the base mount: nfs://real_server_name/vol

Leaf directories and the file names are left off, the full path is available in the files info so there has to be a way to get this information.

EDIT:

After some more digging is seems like I want to use kFSCatInfoParentDirID and kFSCatInfoNodeID to get the parent and node(file) id but I'm not sure how to turn this into something useful.

回答1:

because the FSPathMakeRef, FSGetCatalogInfo and FSCopyURLForVolume are deprecated from Mac OS X 10.8 I modernised the code for get UNC network path on Mac OS X mounted volumes.

    NSError *error=nil; //Error 
    NSURL *volumePath=nil; //result of UNC network mounting path 

    NSString* testPath =@"/Volumes/SCAMBIO/testreport.exe"; //File path to test 

    NSURL *testUrl = [NSURL fileURLWithPath:testPath]; //Create a NSURL from file path
    NSString* mountPath = [testPath stringByDeletingLastPathComponent]; //Get only mounted volume part i.e. /Volumes/SCAMBIO
    NSString* pathComponents = [testPath substringFromIndex:[mountPath length]]; //Get the rest of the path starting after the mounted path i.e. /testereport.exe
   [testUrl getResourceValue:&volumePath forKey:NSURLVolumeURLForRemountingKey error:&error]; //Get real UNC network mounted path i.e. smb://....

    NSLog(@"Path: %@%@", volumePath,pathComponents); //Write result to debug console

The result is in my case, Path: smb://FRANCESCO@192.168.69.44/SCAMBIO/testreport.exe

You need to specify your network mapped volume.

ciao.



回答2:

A solution to this problem was suggested on the Apple Dev Forums, here is the final function I came up with:

- (NSURL *)volumeMountPathFromPath:(NSString *)path{
    NSString *mountPath = nil;
    NSString *testPath = [path copy];
    while(![testPath isEqualToString:@"/"]){
        NSURL *testUrl = [NSURL fileURLWithPath:testPath];
        NSNumber *isVolumeKey;
        [testUrl getResourceValue:&isVolumeKey forKey:NSURLIsVolumeKey error:nil];
        if([isVolumeKey boolValue]){
            mountPath = testPath;
            break;
        }        
        testPath = [testPath stringByDeletingLastPathComponent];
    }

    if(mountPath == nil){
        return nil;
    }

    NSString *pathCompointents = [path substringFromIndex:[mountPath length]];

    FSRef pathRef;
    FSPathMakeRef((UInt8*)[path fileSystemRepresentation], &pathRef, NULL);
    FSCatalogInfo catalogInfo;
    OSErr osErr = FSGetCatalogInfo(&pathRef, kFSCatInfoVolume|kFSCatInfoParentDirID,
                                   &catalogInfo, NULL, NULL, NULL);
    FSVolumeRefNum volumeRefNum = 0;
    if(osErr == noErr){
        volumeRefNum = catalogInfo.volume;
    }

    CFURLRef serverLocation;
    OSStatus result = FSCopyURLForVolume(volumeRefNum, &serverLocation);
    if(result == noErr){
        NSString *fullUrl = [NSString stringWithFormat:@"%@%@", 
                             CFURLGetString(serverLocation), pathCompointents];        
        return [NSURL URLWithString:fullUrl];
    }else{
        NSLog(@"Error getting the mount path: %i", result);
    }
    return nil;
}