My app needs a reference to files that may or may not exist (yet).

When the file exists, I prefer to use the Alias because it tracks if the user moves it, etc. But if the file does not exist yet, my + [NSData aliasRecordFromPath:] method (shown below) returns nil.

It is implied but not explicitly stated in the Alias Manager Reference that you cannot have an Alias to a nonexistent file. My main question: Is this true?

If so, then I need a little MyFileReference class that encapsulates an Alias ^or^ a path. But before I write such a thing, I'm further asking, is such a class is already available somewhere? It seems like something that many developers would need.

On the other hand, if an Alias can refer to a nonexistent file, then presumably my +[NSData aliasRecordFromPath:] can be improved to produce such an alias, and vice versa for my +[NSData pathFromAliasRecord:] method. I'll need something better than FSNewAliasFromPath() which returns -43.

Thanks,

Jerry Krinock


The following is a category on NSData which has two methods, one for converting a path to an alias, and its vice versa. I've cobbled it together from various sources over time.

#import "NSData+FileAlias.h"

@implementation NSData (FileAlias)

+ (NSData*)aliasRecordFromPath:(NSString*)path {
    if ([path length] == 0) {
        return nil ;
    }

    const char* pathC = [path UTF8String] ;

    OSErr osErr ;
    AliasHandle aliasHandle ;
    osErr = FSNewAliasFromPath (
                                NULL,
                                pathC,
                                0,
                                &aliasHandle,
                                NULL
                                ) ;
    NSData* data = nil ;
    if (osErr == noErr) {

#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
        Size size = GetAliasSize(aliasHandle) ;
#else
        Size size = aliasHeader.aliasSize ;
#endif

        AliasPtr aliasPtr = *aliasHandle ;
        data = [NSData dataWithBytes:aliasPtr
                              length:size] ;
    }
    else {
NSLog(@"FSNewAliasFromPath returned OSErr %d for path %s", osErr, pathC) ;
    }

    return data ;
}

- (NSString*)pathFromAliasRecord {
    int err = 0 ;

    unsigned short nBytesAliasRecord ;

    // Cast to an AliasRecord and resolve the alias.
    AliasRecord aliasHeader = *((AliasPtr)[self bytes]) ;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
    AliasPtr ap = &aliasHeader ;
    AliasHandle ah = &ap ;
    nBytesAliasRecord = GetAliasSize(ah) ;
#else
    nBytesAliasRecord = aliasHeader.aliasSize ;
#endif

    Handle handle = NULL;
    FSRef resolvedFSRef;
    if (err <= 0)
    {
        // Move the now-decoded data into the Handle.
if (PtrToHand([self bytes], &handle, nBytesAliasRecord) != noErr)
        {
NSLog(@"Internal Error 589-5451. Can't allocate handle for alias") ;
            err = 1 ;
        }

        Boolean changed;
OSErr osErr = FSResolveAlias(NULL, (AliasHandle)handle, &resolvedFSRef, &changed);

        if (osErr != noErr)
        {
            // File could not be found.  The invoker is responsible to
// raise an error or exception if desired when nil is returned.
            err = 1 ;
        }
    }

    if (handle)
        DisposeHandle(handle);

    char fullPath[4096];
    if (err <= 0)
    {
OSStatus osStatus = FSRefMakePath (&resolvedFSRef, (UInt8*)fullPath, sizeof(fullPath)) ;

        if (osStatus != noErr)
        {
NSLog(@"Internal Error 959-2697. OSStatus %i from FSResolveAlias", osStatus) ;
            err = 1 ;
        }

    }

    NSString* fullPathNSString = nil ;

    if (err <= 0)
        fullPathNSString = [NSString stringWithCString:fullPath] ;

// The full path returned by FSRefMakePath will NOT have a trailing slash UNLESS // the path is the root, i.e. @"/". In that case it will. Thus, in order to return // a standard result to which "/Filename.ext" should be appended, we remove that:
    if ([fullPathNSString length] == 1)
        fullPathNSString = @"" ;

    return [[fullPathNSString retain] autorelease] ;
}

@end
_______________________________________________

Cocoa-dev mailing list ([email protected])

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to