static OSErr GenerateUniqueHFSUniStr(long *startSeed, const FSRef *dir1, const FSRef *dir2, HFSUniStr255 *uniqueName) { OSErr result; long i; FSRefParam pb; FSRef newRef; unsigned char hexStr[17] = "0123456789ABCDEF"; /* set up the parameter block */ pb.name = uniqueName->unicode; pb.nameLength = 8; /* always 8 characters */ pb.textEncodingHint = kTextEncodingUnknown; pb.newRef = &newRef; /* loop until we get fnfErr with a filename in both directories */ result = noErr; while ( fnfErr != result ) { /* convert startSeed to 8 character Unicode string */ uniqueName->length = 8; for ( i = 0; i < 8; ++i ) { uniqueName->unicode[i] = hexStr[((*startSeed >> ((7-i)*4)) & 0xf)]; } /* try in dir1 */ pb.ref = dir1; result = PBMakeFSRefUnicodeSync(&pb); if ( fnfErr == result ) { /* try in dir2 */ pb.ref = dir2; result = PBMakeFSRefUnicodeSync(&pb); if ( fnfErr != result ) { /* exit if anything other than noErr or fnfErr */ require_noerr(result, Dir2PBMakeFSRefUnicodeSyncFailed); } } else { /* exit if anything other than noErr or fnfErr */ require_noerr(result, Dir1PBMakeFSRefUnicodeSyncFailed); } /* increment seed for next pass through loop, */ /* or for next call to GenerateUniqueHFSUniStr */ ++(*startSeed); } /* we have a unique file name which doesn't exist in dir1 or dir2 */ result = noErr; Dir2PBMakeFSRefUnicodeSyncFailed: Dir1PBMakeFSRefUnicodeSyncFailed: return ( result ); }
OSErr FSMakeFSRef( FSVolumeRefNum volRefNum, SInt32 dirID, ConstStr255Param name, FSRef *ref) { OSErr result; FSRefParam pb; pb.ioVRefNum = volRefNum; pb.ioDirID = dirID; pb.ioNamePtr = (StringPtr)name; pb.newRef = ref; #if __LP64__ result = PBMakeFSRefUnicodeSync(&pb); #else result = PBMakeFSRefSync(&pb); #endif // __LP64__ return ( result ); }
URL_TYPE createURLByMakingDirectoryAtURLWithName(URL_TYPE parent, STRING_TYPE name) { CFURLRef newDirectory = NULL; CFAllocatorRef allocator = parent ? CFGetAllocator(parent) : name ? CFGetAllocator(name) : kCFAllocatorDefault; if (parent) parent = CFRetain(parent); else { char *cwdBytes = alloca(PATH_MAX); getcwd(cwdBytes, PATH_MAX); parent = CFURLCreateFromFileSystemRepresentation(allocator, (const unsigned char *)cwdBytes, strlen(cwdBytes), /*isDirectory*/ true); if (!name) { newDirectory = parent; goto end; } } if (!parent) NSLog(CFSTR("in createURLByMakingDirectoryAtURLWithName in CFGrowlAdditions: parent directory URL is NULL (please tell the Growl developers)\n"), parent); else { if (name) name = CFRetain(name); else { name = CFURLCopyLastPathComponent(parent); CFURLRef newParent = CFURLCreateCopyDeletingLastPathComponent(allocator, parent); CFRelease(parent); parent = newParent; } if (!name) NSLog(CFSTR("in createURLByMakingDirectoryAtURLWithName in CFGrowlAdditions: name of directory to create is NULL (please tell the Growl developers)\n"), parent); else { FSRef parentRef; if (!CFURLGetFSRef(parent, &parentRef)) NSLog(CFSTR("in createURLByMakingDirectoryAtURLWithName in CFGrowlAdditions: could not create FSRef for parent directory at %@ (please tell the Growl developers)\n"), parent); else { FSRef newDirectoryRef; struct HFSUniStr255 nameUnicode; CFRange range = { 0, MIN(CFStringGetLength(name), USHRT_MAX) }; CFStringGetCharacters(name, range, nameUnicode.unicode); nameUnicode.length = range.length; struct FSRefParam refPB = { .ref = &parentRef, .nameLength = nameUnicode.length, .name = nameUnicode.unicode, .whichInfo = kFSCatInfoNone, .catInfo = NULL, .textEncodingHint = kTextEncodingUnknown, .newRef = &newDirectoryRef, }; OSStatus err = PBCreateDirectoryUnicodeSync(&refPB); if (err == dupFNErr) { //dupFNErr == file (or folder) exists already. this is fine. err = PBMakeFSRefUnicodeSync(&refPB); } if (err == noErr) { NSLog(CFSTR("PBCreateDirectoryUnicodeSync or PBMakeFSRefUnicodeSync returned %li; calling CFURLCreateFromFSRef"), (long)err); //XXX newDirectory = CFURLCreateFromFSRef(allocator, &newDirectoryRef); NSLog(CFSTR("CFURLCreateFromFSRef returned %@"), newDirectory); //XXX } else NSLog(CFSTR("in createURLByMakingDirectoryAtURLWithName in CFGrowlAdditions: could not create directory '%@' in parent directory at %@: FSCreateDirectoryUnicode returned %li (please tell the Growl developers)"), name, parent, (long)err); } CFRelease(parent); } //if (name) CFRelease(name); } //if (parent) end: return newDirectory; } #ifndef COPYFORK_BUFSIZE # define COPYFORK_BUFSIZE 5242880U /*5 MiB*/ #endif static OSStatus copyFork(const struct HFSUniStr255 *forkName, const FSRef *srcFile, const FSRef *destDir, const struct HFSUniStr255 *destName, FSRef *outDestFile) { OSStatus err, closeErr; struct FSForkIOParam srcPB = { .ref = srcFile, .forkNameLength = forkName->length, .forkName = forkName->unicode, .permissions = fsRdPerm, }; unsigned char debuggingPathBuf[PATH_MAX] = ""; OSStatus debuggingPathErr; err = PBOpenForkSync(&srcPB); if (err != noErr) { debuggingPathErr = FSRefMakePath(srcFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for source file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBOpenForkSync (source: %s) returned %li"), debuggingPathBuf, (long)err); } else { FSRef destFile; /*the first thing to do is get the name of the destination file, if one * wasn't provided. *and while we're at it, we get the catalogue info as well. */ struct FSCatalogInfo catInfo; struct FSRefParam refPB = { .ref = srcFile, .whichInfo = kFSCatInfoGettableInfo & kFSCatInfoSettableInfo, .catInfo = &catInfo, .spec = NULL, .parentRef = NULL, .outName = destName ? NULL : (struct HFSUniStr255 *)(destName = alloca(sizeof(struct HFSUniStr255))), }; err = PBGetCatalogInfoSync(&refPB); if (err != noErr) { debuggingPathErr = FSRefMakePath(srcFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for source file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBGetCatalogInfoSync (source: %s) returned %li"), debuggingPathBuf, (long)err); } else { refPB.ref = destDir; refPB.nameLength = destName->length; refPB.name = destName->unicode; refPB.textEncodingHint = kTextEncodingUnknown; refPB.newRef = &destFile; const char *functionName = "PBMakeFSRefUnicodeSync"; //for error-reporting message err = PBMakeFSRefUnicodeSync(&refPB); if ((err != noErr) && (err != fnfErr)) { handleMakeFSRefError: debuggingPathErr = FSRefMakePath(destDir, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for destination directory: FSRefMakePath returned %li)", (long)debuggingPathErr); //get filename too CFStringRef debuggingFilename = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, destName->unicode, destName->length, /*contentsDeallocator*/ kCFAllocatorNull); if (!debuggingFilename) debuggingFilename = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, "(could not get filename for destination file: CFStringCreateWithCharactersNoCopy returned NULL)", kCFStringEncodingASCII, /*contentsDeallocator*/ kCFAllocatorNull); NSLog(CFSTR("in copyFork in CFGrowlAdditions: %s (destination: %s/%@) returned %li"), functionName, debuggingPathBuf, debuggingFilename, (long)err); if (debuggingFilename) CFRelease(debuggingFilename); } else { //that file doesn't exist in that folder; create it. err = PBCreateFileUnicodeSync(&refPB); if (err == noErr) { /*make sure the Finder knows about the new file. *FNNotify returns a status code too, but this isn't an * essential step, so we just ignore it. */ FNNotify(destDir, kFNDirectoryModifiedMessage, kNilOptions); } else if (err == dupFNErr) { /*dupFNErr: the file already exists. *we can safely ignore this error. */ err = noErr; } else { functionName = "PBCreateFileUnicodeSync"; goto handleMakeFSRefError; } } } if (err == noErr) { if (outDestFile) memcpy(outDestFile, &destFile, sizeof(destFile)); struct FSForkIOParam destPB = { .ref = &destFile, .forkNameLength = forkName->length, .forkName = forkName->unicode, .permissions = fsWrPerm, }; err = PBOpenForkSync(&destPB); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBOpenForkSync (dest) returned %li"), (long)err); if (err != noErr) { debuggingPathErr = FSRefMakePath(&destFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for dest file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBOpenForkSync (destination: %s) returned %li"), debuggingPathBuf, (long)err); } else { void *buf = malloc(COPYFORK_BUFSIZE); if (buf) { srcPB.buffer = destPB.buffer = buf; srcPB.requestCount = COPYFORK_BUFSIZE; while (err == noErr) { err = PBReadForkSync(&srcPB); if (err == eofErr) { err = noErr; if (srcPB.actualCount == 0) break; } if (err != noErr) { debuggingPathErr = FSRefMakePath(&destFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for source file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBReadForkSync (source: %s) returned %li"), debuggingPathBuf, (long)err); } else { destPB.requestCount = srcPB.actualCount; err = PBWriteForkSync(&destPB); if (err != noErr) { debuggingPathErr = FSRefMakePath(&destFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for dest file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBWriteForkSync (destination: %s) returned %li"), debuggingPathBuf, (long)err); } } } free(buf); } closeErr = PBCloseForkSync(&destPB); if (closeErr != noErr) { debuggingPathErr = FSRefMakePath(&destFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for dest file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBCloseForkSync (destination: %s) returned %li"), debuggingPathBuf, (long)err); } if (err == noErr) err = closeErr; } } closeErr = PBCloseForkSync(&srcPB); if (closeErr != noErr) { debuggingPathErr = FSRefMakePath(&destFile, debuggingPathBuf, PATH_MAX); if (debuggingPathErr != noErr) snprintf((char *)debuggingPathBuf, PATH_MAX, "(could not get path for source file: FSRefMakePath returned %li)", (long)debuggingPathErr); NSLog(CFSTR("in copyFork in CFGrowlAdditions: PBCloseForkSync (source: %s) returned %li"), debuggingPathBuf, (long)err); } if (err == noErr) err = closeErr; } return err; } static OSStatus GrowlCopyObjectSync(const FSRef *fileRef, const FSRef *destRef, FSRef *destFileRef) { OSStatus err; struct HFSUniStr255 forkName; struct FSForkIOParam forkPB = { .ref = fileRef, .forkIterator = { .initialize = 0L }, .outForkName = &forkName, }; do { err = PBIterateForksSync(&forkPB); NSLog(CFSTR("PBIterateForksSync returned %li"), (long)err); if (err != noErr) { if (err != errFSNoMoreItems) NSLog(CFSTR("in GrowlCopyObjectSync in CFGrowlAdditions: PBIterateForksSync returned %li"), (long)err); } else { err = copyFork(&forkName, fileRef, destRef, /*destName*/ NULL, /*outDestFile*/ destFileRef); //copyFork prints its own error messages } } while (err == noErr); if (err == errFSNoMoreItems) err = noErr; return err; } CFURLRef createURLByCopyingFileFromURLToDirectoryURL(CFURLRef file, CFURLRef dest) { CFURLRef destFileURL = NULL; FSRef fileRef, destRef, destFileRef; Boolean gotFileRef = CFURLGetFSRef(file, &fileRef); Boolean gotDestRef = CFURLGetFSRef(dest, &destRef); if (!gotFileRef) NSLog(CFSTR("in createURLByCopyingFileFromURLToDirectoryURL in CFGrowlAdditions: CFURLGetFSRef failed with source URL %@"), file); else if (!gotDestRef) NSLog(CFSTR("in createURLByCopyingFileFromURLToDirectoryURL in CFGrowlAdditions: CFURLGetFSRef failed with destination URL %@"), dest); else { OSStatus err; /* * 10.2 has a problem with weak symbols in frameworks so we use * MAC_OS_X_VERSION_MIN_REQUIRED >= 10.3. */ #if defined(NSAppKitVersionNumber10_3) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3 if (FSCopyObjectSync) { err = FSCopyObjectSync(&fileRef, &destRef, /*destName*/ NULL, &destFileRef, kFSFileOperationOverwrite); } else { #endif err = GrowlCopyObjectSync(&fileRef, &destRef, &destFileRef); #if defined(NSAppKitVersionNumber10_3) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3 } #endif if (err == noErr) destFileURL = CFURLCreateFromFSRef(kCFAllocatorDefault, &destFileRef); else NSLog(CFSTR("in createURLByCopyingFileFromURLToDirectoryURL in CFGrowlAdditions: CopyObjectSync returned %li for source URL %@"), (long)err, file); } return destFileURL; }
int ReadTOCData (FSVolumeRefNum theVolume, SDL_CD *theCD) { HFSUniStr255 dataForkName; OSStatus theErr; FSIORefNum forkRefNum; SInt64 forkSize; Ptr forkData = 0; ByteCount actualRead; CFDataRef dataRef = 0; CFPropertyListRef propertyListRef = 0; FSRefParam fsRefPB; FSRef tocPlistFSRef; FSRef rootRef; const char* error = "Unspecified Error"; const UniChar uniName[] = { '.','T','O','C','.','p','l','i','s','t' }; theErr = FSGetVolumeInfo(theVolume, 0, 0, kFSVolInfoNone, 0, 0, &rootRef); if(theErr != noErr) { error = "FSGetVolumeInfo"; goto bail; } SDL_memset(&fsRefPB, '\0', sizeof (fsRefPB)); fsRefPB.ref = &rootRef; fsRefPB.newRef = &tocPlistFSRef; fsRefPB.nameLength = sizeof (uniName) / sizeof (uniName[0]); fsRefPB.name = uniName; fsRefPB.textEncodingHint = kTextEncodingUnknown; theErr = PBMakeFSRefUnicodeSync (&fsRefPB); if(theErr != noErr) { error = "PBMakeFSRefUnicodeSync"; goto bail; } theErr = FSGetDataForkName (&dataForkName); if (theErr != noErr) { error = "FSGetDataForkName"; goto bail; } theErr = FSOpenFork (&tocPlistFSRef, dataForkName.length, dataForkName.unicode, fsRdPerm, &forkRefNum); if (theErr != noErr) { error = "FSOpenFork"; goto bail; } theErr = FSGetForkSize (forkRefNum, &forkSize); if (theErr != noErr) { error = "FSGetForkSize"; goto bail; } forkData = NewPtr (forkSize); if(forkData == NULL) { error = "NewPtr"; goto bail; } theErr = FSReadFork (forkRefNum, fsFromStart, 0 , forkSize, forkData, &actualRead); if(theErr != noErr) { error = "FSReadFork"; goto bail; } dataRef = CFDataCreate (kCFAllocatorDefault, (UInt8 *)forkData, forkSize); if(dataRef == 0) { error = "CFDataCreate"; goto bail; } propertyListRef = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, dataRef, kCFPropertyListImmutable, NULL); if (propertyListRef == NULL) { error = "CFPropertyListCreateFromXMLData"; goto bail; } if(CFGetTypeID(propertyListRef)== CFDictionaryGetTypeID()) { CFDictionaryRef dictRef = (CFDictionaryRef)propertyListRef; CFDataRef theRawTOCDataRef; CFArrayRef theSessionArrayRef; CFIndex numSessions; CFIndex index; theRawTOCDataRef = (CFDataRef)CFDictionaryGetValue (dictRef, CFSTR(kRawTOCDataString)); theSessionArrayRef = (CFArrayRef)CFDictionaryGetValue (dictRef, CFSTR(kSessionsString)); numSessions = CFArrayGetCount (theSessionArrayRef); theCD->numtracks = 0; for(index = 0; index < numSessions; index++) { CFDictionaryRef theSessionDict; CFNumberRef leadoutBlock; CFArrayRef trackArray; CFIndex numTracks; CFIndex trackIndex; UInt32 value = 0; theSessionDict = (CFDictionaryRef) CFArrayGetValueAtIndex (theSessionArrayRef, index); leadoutBlock = (CFNumberRef) CFDictionaryGetValue (theSessionDict, CFSTR(kLeadoutBlockString)); trackArray = (CFArrayRef)CFDictionaryGetValue (theSessionDict, CFSTR(kTrackArrayString)); numTracks = CFArrayGetCount (trackArray); for(trackIndex = 0; trackIndex < numTracks; trackIndex++) { CFDictionaryRef theTrackDict; CFNumberRef trackNumber; CFNumberRef sessionNumber; CFNumberRef startBlock; CFBooleanRef isDataTrack; UInt32 value; theTrackDict = (CFDictionaryRef) CFArrayGetValueAtIndex (trackArray, trackIndex); trackNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kPointKeyString)); sessionNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kSessionNumberKeyString)); startBlock = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kStartBlockKeyString)); isDataTrack = (CFBooleanRef) CFDictionaryGetValue (theTrackDict, CFSTR(kDataKeyString)); int idx = theCD->numtracks++; CFNumberGetValue (trackNumber, kCFNumberSInt32Type, &value); theCD->track[idx].id = value; CFNumberGetValue (startBlock, kCFNumberSInt32Type, &value); theCD->track[idx].offset = value; theCD->track[idx].type = (isDataTrack == kCFBooleanTrue) ? SDL_DATA_TRACK : SDL_AUDIO_TRACK; if (trackIndex > 0) { theCD->track[idx-1].length = theCD->track[idx].offset - theCD->track[idx-1].offset; } } CFNumberGetValue (leadoutBlock, kCFNumberSInt32Type, &value); theCD->track[theCD->numtracks-1].length = value - theCD->track[theCD->numtracks-1].offset; theCD->track[theCD->numtracks].offset = value; } } theErr = 0; goto cleanup; bail: SDL_SetError ("ReadTOCData: %s returned %d", error, theErr); theErr = -1; cleanup: if (propertyListRef != NULL) CFRelease(propertyListRef); if (dataRef != NULL) CFRelease(dataRef); if (forkData != NULL) DisposePtr(forkData); FSCloseFork (forkRefNum); return theErr; }