Ejemplo n.º 1
0
unsigned int
XMLMacCarbonFile::size()
{
    OSErr err = noErr;
    unsigned int len = 0;

    if (!mFileValid)
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetSize);

    if (gHasHFSPlusAPIs)
    {
        SInt64 bigLen = 0;
        err = FSGetForkSize(mFileRefNum, &bigLen);
        if (err == noErr)
            len = bigLen;
    }
    else
    {
        long longLen;
        err = GetEOF(mFileRefNum, &longLen);
        if (err == noErr)
            len = longLen;
    }

    if (err != noErr)
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetSize);

    return len;
}
Ejemplo n.º 2
0
	XMP_Int64 LFA_Measure ( LFA_FileRef file )
	{
		long refNum = (long)file;	// ! Use long to avoid size warnings for SInt16 cast.
		XMP_Int64 length;

		OSErr err = FSGetForkSize ( refNum, &length );
		if ( err != noErr ) LFA_Throw ( "LFA_Measure: FSSetForkSize failure", kLFAErr_ExternalFailure );

		return length;

	}	// LFA_Measure
Ejemplo n.º 3
0
AP4_Result
My_ByteStream::GetSize(AP4_LargeSize &size)
{
#ifdef PRWIN_ENV
	size = GetFileSize(_fp, NULL);
	
	return AP4_SUCCESS;
#else
	SInt64 fork_size = 0;
	
	OSErr result = FSGetForkSize(CAST_REFNUM(_fp), &fork_size);
	
	size = fork_size;
		
	return (result == noErr ? AP4_SUCCESS : AP4_FAILURE);
#endif
}
Ejemplo n.º 4
0
::FLAC__StreamDecoderLengthStatus
OurDecoder::length_callback(FLAC__uint64 *stream_length)
{
#ifdef PRWIN_ENV
	LARGE_INTEGER lpos;

	BOOL result = GetFileSizeEx(_fp, &lpos);
	
	*stream_length = lpos.QuadPart;
	
	return (result ? FLAC__STREAM_DECODER_LENGTH_STATUS_OK : FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR);
#else
	SInt64 fork_size = 0;
	
	OSErr result = FSGetForkSize(CAST_REFNUM(_fp), &fork_size);
		
	*stream_length = fork_size;
	
	return (result == noErr ? FLAC__STREAM_DECODER_LENGTH_STATUS_OK : FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR);
#endif
}
Ejemplo n.º 5
0
//*** kind of a hack, TOTEST
bool LFA_isEof( LFA_FileRef file )
{
	#if XMP_MacBuild
		long refNum = (long)file;	// ! Use long to avoid size warnings for SInt16 cast.

		XMP_Int64 position, length;
		OSErr err = FSGetForkPosition( refNum, &position );
		if ( err != noErr )
			LFA_Throw ( "LFA_isEOF:FSGetForkPosition failure", kLFAErr_ExternalFailure );

		err = FSGetForkSize ( refNum, &length );
		if ( err != noErr )
			LFA_Throw ( "LFA_isEof: FSGetForkSize failure", kLFAErr_ExternalFailure );

		return position==length;
	#endif

	#if XMP_WinBuild
		HANDLE handle = (HANDLE)file;

		XMP_Int64 filepos = LFA_Tell(file);

		DWORD lowWord, highWord;
		lowWord = GetFileSize(handle, &highWord);
		XMP_Int64 filesize = ( ((XMP_Int64)highWord) << 32 | lowWord );

		return filesize == filepos;
	#endif

	#if XMP_UNIXBuild || XMP_iOSBuild
		int descr = (int)file;

		struct stat info;
		if (fstat(descr,&info) == -1)
		  LFA_Throw ( "LFA_isEof: fstat failed.", kLFAErr_ExternalFailure );

		return LFA_Tell(file) == info.st_size;
	#endif
}
Ejemplo n.º 6
0
/********************************************************************
*	 GetFileSize
********************************************************************/
DWORD GetFileSize(	HANDLE hFile,			/* handle to file */
					DWORD *ulOffSetHigh )	/* high-order word of file size */
{
	SInt64	fileLength;
	OSErr	theErr;

	if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE))
	{
		SetLastError(theErr);
		return -1u;
	}
	
	theErr = FSGetForkSize((short)(long)hFile, &fileLength);
	if (theErr != noErr)
	{
		SetLastError(theErr);
		return -1u;
	}
	
	if (ulOffSetHigh != NULL)
	{
		*ulOffSetHigh = fileLength >> 32;
	}
Ejemplo n.º 7
0
OSErr SplitFileIfNeeded(FSRef * inFileReference,FSRef * inParentReference,FSCatalogInfo * inFileCatalogInfo,HFSUniStr255 * inFileName)
{
	OSErr tErr;
	Boolean splitNeeded=FALSE;
	SInt16 tForkRefNum;
	UInt32 tResourceForkSize=0;
	static HFSUniStr255 sResourceForkName={0,{}};
	Boolean hasResourceFork=FALSE;
	static UInt8 tPOSIXPath[PATH_MAX*2+1];
	static UInt32 tPOSIXPathMaxLength=PATH_MAX*2;
	struct stat tFileStat;
	SInt16 tNewFileRefNum;
	
	if (sResourceForkName.length==0)
	{
		tErr=FSGetResourceForkName(&sResourceForkName);
	
		if (tErr!=noErr)
		{
			logerror("An error occurred when obtaining the ResourceFork name\n");
			
			return -1;
		}
	}
	
	// 1. Check for the presence of a resource fork
		
	tErr=FSOpenFork(inFileReference,sResourceForkName.length,sResourceForkName.unicode,fsRdPerm,&tForkRefNum);
	
	if (tErr==noErr)
	{
		SInt64 tForkSize;
		
		// Get the size of the resource fork
		
		tErr=FSGetForkSize(tForkRefNum,&tForkSize);
		
		if (tErr!=noErr)
		{
			logerror("An error occurred on getting the resource fork size of a file or director\n");
			
			FSCloseFork(tForkRefNum);
			
			return -1;
		}
		
		if (tForkSize>0xFFFFFFFF)
		{
			FSCloseFork(tForkRefNum);
			
			// AppleDouble File format does not support forks bigger than 2GB
			
			logerror("AppleDouble file format does not support forks bigger than 2 GB\n");
			
			return -1;
		}
		
		tResourceForkSize=tForkSize;
		
		if (tForkSize>0)
		{
			hasResourceFork=TRUE;
		
			splitNeeded=TRUE;
		}
		else
		{
			FSCloseFork(tForkRefNum);
		}
	}
	else
	{
		switch(tErr)
		{
			case errFSForkNotFound:
			case eofErr:
				// No resource Fork
				
				tErr=noErr;
				break;
			default:
				
				logerror("Unable to open fork\n");
				
				return -1;
				
				break;
		}
	}
	
	// 2. Check for the presence of FinderInfo or ExtFinderInfo
	
	if (splitNeeded==FALSE)
	{
		UInt32 * tUnsignedInt32Ptr;
		int i;
		
		
		// 1. We need to save the Folder(Ext) Info in the ._ file if there are any folder/finder or extend folder/finder info
			
		tUnsignedInt32Ptr= (UInt32 *) inFileCatalogInfo->finderInfo;
		
		for(i=0;i<4;i++)
		{
			if (tUnsignedInt32Ptr[i]!=0)
			{
				// We need to create a ._file
			
				splitNeeded=TRUE;
				break;
			}
		}
		
		if (splitNeeded==TRUE)		// 01/02/07: Symbolic link looks like this
		{
			UInt32 tSymbolicLink;

			tSymbolicLink='s';
			tSymbolicLink='l'+(tSymbolicLink<<8);
			tSymbolicLink='n'+(tSymbolicLink<<8);
			tSymbolicLink='k'+(tSymbolicLink<<8);

			if (tUnsignedInt32Ptr[0]==tSymbolicLink)
			{
				splitNeeded=FALSE;
			}
		}
		else
		{
			tUnsignedInt32Ptr= (UInt32 *) inFileCatalogInfo->extFinderInfo;
		
			for(i=0;i<4;i++)
			{
				if (tUnsignedInt32Ptr[i]!=0)
				{
					// We need to create a ._file
				
					splitNeeded=TRUE;
					break;
				}
			}
		}
	}
	
	// 3. Split if needed
	
	if (splitNeeded==TRUE)
	{
		FSRef tNewFileReference;
		HFSUniStr255 tNewFileName;
	
		// Get the absolute Posix Path Name
		
		tErr=FSRefMakePath(inFileReference,tPOSIXPath,tPOSIXPathMaxLength);
		
		if (tErr==noErr)
		{
			if (lstat((char *) tPOSIXPath,&tFileStat)==-1)
			{
				switch(errno)
				{
					case ENOENT:
						// A COMPLETER
						
						break;
					default:
						// A COMPLETER
						
						break;
				}
				
				tErr=-1;
				
				goto byebye;
			}
		}
		else
		{
			logerror("An error occurred when trying to get the absolute path of a file or directory\n");
			
			tErr=-1;
				
			goto byebye;
		}
		
		if (gVerboseMode==TRUE)
		{
			printf("    splitting %s...\n",tPOSIXPath);
		}
		
		// Check that we do not explode the current limit for file names
		
		if (inFileName->length>gMaxFileNameLength)
		{
			// We do not have enough space to add the ._ prefix
		
			// The file name is too long
					
			// Write the error
			
			logerror("File name is too long. The maximum length allowed is %ld characters\n",gMaxFileNameLength+2);
			
			return -1;
		}
		
		tNewFileName.length=inFileName->length+2;
		
		tNewFileName.unicode[0]='.';
		tNewFileName.unicode[1]='_';
		
		BlockMoveData(inFileName->unicode,tNewFileName.unicode+2,inFileName->length*sizeof(UniChar));
		
		// We need to create a ._file
		
tryagain:

		tErr=FSCreateFileUnicode(inParentReference,tNewFileName.length,tNewFileName.unicode,0,NULL,&tNewFileReference,NULL);
		
		if (tErr!=noErr)
		{
			switch(tErr)
			{
				case bdNamErr:
				case fsmBadFFSNameErr:
				case errFSNameTooLong:
					// The file name is too long
					
					// Write the error
					
					logerror("File name is too long. The maximum length allowed is %ld characters\n",gMaxFileNameLength+2);
					
					break;
				case dskFulErr:
					
					logerror("Disk is full\n");
					
					break;
					
				case errFSQuotaExceeded:
					
					logerror("Your quota are exceeded\n");
					
					break;
				case dupFNErr:
				
					// The file already exists, we need to try to delete it before recreating it
					
					tErr=FSMakeFSRefUnicode(inParentReference,tNewFileName.length,tNewFileName.unicode,kTextEncodingDefaultFormat,&tNewFileReference);
					
					if (tErr==noErr)
					{
						// Delete the current ._file
						
						tErr=FSDeleteObject(&tNewFileReference);
						
						if (tErr==noErr)
						{
							goto tryagain;
						}
						else
						{
							// A COMPLETER
						}
					}
					else
					{
						// A COMPLETER
					}
					
					break;
				
				case afpVolLocked:
					// A COMPLETER
					break;
					
				default:
					// A COMPLETER
					break;
			}
			
			return -1;
		}
		
		tErr=FSOpenFork(&tNewFileReference,0,NULL,fsWrPerm,&tNewFileRefNum);
		
		if (tErr==noErr)
		{
			unsigned char tAppleDoubleMagicNumber[4]=  {0x00,0x05,0x16,0x07};
			unsigned char tAppleDoubleVersionNumber[4]={0x00,0x02,0x00,0x00};
			unsigned char tAppleDoubleFiller[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
			ByteCount tRequestCount;
			UInt16 tNumberOfEntries;
			UInt16 tSwappedNumberOfEntries;

			UInt32 tEntryID;
			UInt32 tEntryOffset;
			UInt32 tEntryLength;
			
			// Write the Magic Number
			
			tRequestCount=4;
			
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,tAppleDoubleMagicNumber,NULL);
			
			if (tErr!=noErr)
			{
				goto writebail;
			}
			
			// Write the Version Number
			
			tRequestCount=4;
			
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,tAppleDoubleVersionNumber,NULL);
			
			if (tErr!=noErr)
			{
				goto writebail;
			}
			
			// Write the Filler
			
			tRequestCount=16;
			
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,tAppleDoubleFiller,NULL);
			
			if (tErr!=noErr)
			{
				goto writebail;
			}
			
			// Compute the Number of Entries
			
			tNumberOfEntries=0x0002;
			
			tSwappedNumberOfEntries=tNumberOfEntries;
			
#ifdef __LITTLE_ENDIAN__
			
			// Swap for Intel processor
			
			tSwappedNumberOfEntries=CFSwapInt16(tSwappedNumberOfEntries);

#endif			
			tRequestCount=2;
			
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tSwappedNumberOfEntries,NULL);
			
			if (tErr!=noErr)
			{
				goto writebail;
			}
			
			// Write the Entries Descriptor
			
			// **** Finder Info
			
			tEntryID=0x00000009;		// Finder Info ID
			
			tEntryOffset=0x0000001A+tNumberOfEntries*12;
			
			tEntryLength=0x00000020;	// 32 bytes
			
#ifdef __LITTLE_ENDIAN__
			
			// Swap for Intel processor
			
			tEntryID=CFSwapInt32(tEntryID);
			
			tEntryOffset=CFSwapInt32(tEntryOffset);
			
			tEntryLength=CFSwapInt32(tEntryLength);
			
#endif			
			tRequestCount=4;
			
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryID,NULL);
			
			if (tErr!=noErr)
			{
				goto writebail;
			}
			
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryOffset,NULL);
			
			if (tErr!=noErr)
			{
				goto writebail;
			}
			
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryLength,NULL);
			
			if (tErr!=noErr)
			{
				goto writebail;
			}
			
			tEntryID=0x00000002;		// Resource Fork ID
				
			tEntryOffset=0x00000052;
				
			if (hasResourceFork==TRUE)
			{
				// **** Finder Info
			
				tEntryLength=tResourceForkSize;	// As you can see the AppleDouble format file is not ready for forks bigger than 2 GB
			}
			else
			{
				tEntryLength=0;
			}
			
#ifdef __LITTLE_ENDIAN__
				
			// Swap for Intel processor
		
			tEntryID=CFSwapInt32(tEntryID);
			
			tEntryOffset=CFSwapInt32(tEntryOffset);
			
			tEntryLength=CFSwapInt32(tEntryLength);
#endif

			tRequestCount=4;
			
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryID,NULL);
			
			if (tErr!=noErr)
			{
				goto writebail;
			}
			
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryOffset,NULL);
			
			if (tErr!=noErr)
			{
				goto writebail;
			}
		
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryLength,NULL);
		
			if (tErr!=noErr)
			{
				goto writebail;
			}
			
			// Write the Entries
			
			// **** Write Finder Info
			
#ifdef __LITTLE_ENDIAN__

			// Intel Processors
			
			// Even though it's referenced as a bytes field in the File API, this is actually a structure we need to swap...

			if (inFileCatalogInfo->nodeFlags & kFSNodeIsDirectoryMask)
			{
				// It's a fragging folder
			
				FolderInfo * tFolderInfoStruct;
				ExtendedFolderInfo * tExtendedFolderInfoStruct;
				
				// Swap FolderInfo Structure
				
				tFolderInfoStruct=(FolderInfo *) inFileCatalogInfo->finderInfo;
				
				SWAP_RECT(tFolderInfoStruct->windowBounds);
				tFolderInfoStruct->finderFlags=CFSwapInt16(tFolderInfoStruct->finderFlags);
				SWAP_POINT(tFolderInfoStruct->location);
				tFolderInfoStruct->reservedField=CFSwapInt16(tFolderInfoStruct->reservedField);
				
				// Swap ExtendedFolderInfo Info Structure
				
				tExtendedFolderInfoStruct=(ExtendedFolderInfo *) inFileCatalogInfo->extFinderInfo;
				
				SWAP_POINT(tExtendedFolderInfoStruct->scrollPosition);
				tExtendedFolderInfoStruct->reserved1=CFSwapInt32(tExtendedFolderInfoStruct->reserved1);
				tExtendedFolderInfoStruct->extendedFinderFlags=CFSwapInt16(tExtendedFolderInfoStruct->extendedFinderFlags);
				tExtendedFolderInfoStruct->reserved2=CFSwapInt16(tExtendedFolderInfoStruct->reserved2);
				tExtendedFolderInfoStruct->putAwayFolderID=CFSwapInt32(tExtendedFolderInfoStruct->putAwayFolderID);
			}
			else
			{
				// I'm just a file, you know
				
				FileInfo * tFileInfoStruct;
				ExtendedFileInfo * tExtendedFileInfoStruct;
				
				// Swap FileInfo Structure
				
				tFileInfoStruct=(FileInfo *) inFileCatalogInfo->finderInfo;
				
				tFileInfoStruct->fileType=CFSwapInt32(tFileInfoStruct->fileType);
				tFileInfoStruct->fileCreator=CFSwapInt32(tFileInfoStruct->fileCreator);
				tFileInfoStruct->finderFlags=CFSwapInt16(tFileInfoStruct->finderFlags);
				SWAP_POINT(tFileInfoStruct->location);
				tFileInfoStruct->reservedField=CFSwapInt16(tFileInfoStruct->reservedField);
				
				// Swap ExtendedFileInfo Structure
				
				tExtendedFileInfoStruct=(ExtendedFileInfo *) inFileCatalogInfo->extFinderInfo;
				
				tExtendedFileInfoStruct->reserved1[0]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[0]);
				tExtendedFileInfoStruct->reserved1[1]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[1]);
				tExtendedFileInfoStruct->reserved1[2]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[2]);
				tExtendedFileInfoStruct->reserved1[3]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[3]);
				tExtendedFileInfoStruct->extendedFinderFlags=CFSwapInt16(tExtendedFileInfoStruct->extendedFinderFlags);
				tExtendedFileInfoStruct->reserved2=CFSwapInt16(tExtendedFileInfoStruct->reserved2);
				tExtendedFileInfoStruct->putAwayFolderID=CFSwapInt32(tExtendedFileInfoStruct->putAwayFolderID);
			}

#endif
			
			tRequestCount=16;
				
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,inFileCatalogInfo->finderInfo,NULL);
				
			if (tErr!=noErr)
			{
				goto writebail;
			}
				
			tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,inFileCatalogInfo->extFinderInfo,NULL);
				
			if (tErr!=noErr)
			{
				goto writebail;
			}
			
			// **** Write Resource Fork?
			
			if (hasResourceFork==TRUE)
			{
				// We need to be clever and copy the Resource Fork by chunks to avoid using too much memory
				
				static UInt8 * tBuffer=NULL;
				static ByteCount tReadRequestCount=0;
				ByteCount tReadActualCount;
				OSErr tReadErr;

#define GOLDIN_BUFFER_ONE_MEGABYTE_SIZE		1048576
				
				if (tBuffer==NULL)
				{
					tReadRequestCount=GOLDIN_BUFFER_ONE_MEGABYTE_SIZE;
					
					do
					{
						tBuffer=(UInt8 *) malloc(tReadRequestCount*sizeof(UInt8));
					
						tReadRequestCount/=2;
					}
					while (tBuffer==NULL && tReadRequestCount>1);
					
					if (tBuffer!=NULL && tReadRequestCount>1)
					{
						tReadRequestCount*=2;
					}
					else
					{
						// A COMPLETER
					}
				}
				
				do
				{
					tReadErr=FSReadFork(tForkRefNum, fsAtMark,0, tReadRequestCount, tBuffer, &tReadActualCount);
					
					if (tReadErr==noErr || tReadErr==eofErr)
					{
						tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tReadActualCount,tBuffer,NULL);
						
						if (tErr!=noErr)
						{
							break;
						}
					}
					else
					{
						break;
					}
				
				}
				while (tReadErr!=eofErr);
				
				if (tReadErr!=eofErr)
				{
					// A problem occurred while reading the Resource Fork
					
					goto writebail;
				}
				else
				if (tErr!=noErr)
				{
					// A problem occurred while writing the Resource Fork Data to the AppleDouble file
					
					goto writebail;
				}
			}
		
			tErr=FSCloseFork(tNewFileRefNum);
			
			tErr=noErr;
			
			// Set the owner
			
			tErr=FSSetCatalogInfo(&tNewFileReference,kFSCatInfoPermissions,inFileCatalogInfo);
			
			if (tErr!=noErr)
			{
				//logerror("Permissions, owner and group could not be set for the AppleDouble file of %s\n",tPOSIXPath);
				
				tErr=-1;
				
				goto byebye;
			}
		}
		else
		{
			// A COMPLETER
		}
		
		// Close the Resource Fork if needed
		
		if (hasResourceFork==TRUE)
		{
			tErr=FSCloseFork(tForkRefNum);
		
			if (gStripResourceForks==TRUE && tErr==noErr)
			{
				// Strip the resource fork
				
				tErr=FSDeleteFork(inFileReference,sResourceForkName.length,sResourceForkName.unicode);
				
				if (tErr!=noErr)
				{
					switch(tErr)
					{
						case errFSForkNotFound:
							// This is not important
							tErr=noErr;
							break;
						default:
							// A COMPLETER
							break;
					}
				}
			}
			else
			{
				if (gStripResourceForks==TRUE && tErr!=noErr)
				{
					logerror("Resource Fork could not be stripped from %s\n",tPOSIXPath);
				
					// A COMPLETER
				}
			}
		}
	}
	
	return tErr;
	
writebail:

	switch(tErr)
	{
		case dskFulErr:
			logerror("Disk is full\n");
			break;
		case errFSQuotaExceeded:
			logerror("Your quota are exceeded\n");
			break;
		default:
			logerror("An unknown error occurred while writing the AppleDouble file of %s\n",tPOSIXPath);
			break;
	}
	
	FSCloseFork(tNewFileRefNum);
	
byebye:

	if (hasResourceFork==TRUE)
	{
		FSCloseFork(tForkRefNum);
	}
	
	return tErr;
}
Ejemplo n.º 8
0
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;
}