Referring to file by Alias ^or^ path
Referring to file by Alias ^or^ path
- Subject: Referring to file by Alias ^or^ path
- From: Jerry Krinock <email@hidden>
- Date: Mon, 1 Jun 2009 16:56:55 -0700
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@hidden)
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:
This email sent to email@hidden