/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ // AppleCDDAFileSystemUtils.c created by CJS on Sun 14-May-2000 #ifndef __APPLE_CDDA_FS_UTILS_H__ #include "AppleCDDAFileSystemUtils.h" #endif #ifndef __APPLE_CDDA_FS_DEBUG_H__ #include "AppleCDDAFileSystemDebug.h" #endif #ifndef __APPLE_CDDA_FS_DEFINES_H__ #include "AppleCDDAFileSystemDefines.h" #endif #ifndef __AIFF_SUPPORT_H__ #include "AIFFSupport.h" #endif #ifndef __APPLE_CDDA_FS_VFS_OPS_H__ #include "AppleCDDAFileSystemVFSOps.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Globals //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ char gFileSuffix[5] = ".aiff"; enum { kASCIINumberZero = 0x30 // '0' }; enum { kAlbumTrackNumber = 0 }; //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Static Function Prototypes //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ static int BuildTrackName ( struct mount * mountPtr, AppleCDDANodeInfoPtr nodeInfoPtr ); static UInt32 CalculateNumberOfDescriptors ( const QTOCDataFormat10Ptr TOCDataPtr ); static UInt32 CalculateLBA ( SubQTOCInfoPtr trackDescriptorPtr ); static int FindName ( struct mount * mountPtr, UInt8 trackNumber, char ** name, UInt8 * nameSize ); //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // CreateNewCDDANode - This routine is responsible for creating new nodes //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ int CreateNewCDDANode ( struct mount * mountPtr, UInt32 nodeID, struct proc * procPtr, struct vnode ** vNodeHandle ) { int result = 0; AppleCDDANodePtr cddaNodePtr = NULL; struct vnode * vNodePtr = NULL; DebugAssert ( ( mountPtr != NULL ) ); DebugAssert ( ( procPtr != NULL ) ); DebugAssert ( ( vNodeHandle != NULL ) ); // Allocate the cddaNode MALLOC ( cddaNodePtr, AppleCDDANodePtr, sizeof ( AppleCDDANode ), M_TEMP, M_WAITOK ); // Zero the structure bzero ( cddaNodePtr, sizeof ( *cddaNodePtr ) ); // Init the node lock lockinit ( &cddaNodePtr->lock, PINOD, "cddanode", 0, 0 ); // Set the nodeID cddaNodePtr->nodeID = nodeID; // Note that getnewvnode ( ) returns the vnode with a refcount of +1; // this routine returns the newly created vnode with this positive refcount. result = getnewvnode ( VT_CDDA, mountPtr, gCDDA_VNodeOp_p, &vNodePtr ); if ( result != 0 ) { DebugLog ( ( "getnewvnode failed with error code %d\n", result ) ); goto FREE_CDDA_NODE_ERROR; } // Link the vnode and cddaNode together vNodePtr->v_data = cddaNodePtr; cddaNodePtr->vNodePtr = vNodePtr; // Stuff the vnode in *vNodeHandle = vNodePtr; return result; FREE_CDDA_NODE_ERROR: // Free the allocated memory FREE ( ( caddr_t ) cddaNodePtr, M_TEMP ); cddaNodePtr = NULL; return result; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // DisposeCDDANode - This routine is responsible for cleaning up cdda nodes //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ int DisposeCDDANode ( struct vnode * vNodePtr, struct proc * theProcPtr ) { AppleCDDANodePtr cddaNodePtr = NULL; AppleCDDAMountPtr cddaMountPtr = NULL; DebugAssert ( ( vNodePtr != NULL ) ); cddaNodePtr = VTOCDDA ( vNodePtr ); cddaMountPtr = VFSTOCDDA ( vNodePtr->v_mount ); DebugAssert ( ( cddaNodePtr != NULL ) ); DebugAssert ( ( cddaMountPtr != NULL ) ); if ( cddaNodePtr != NULL ) { // Check if it's a directory or a file if ( cddaNodePtr->nodeType == kAppleCDDADirectoryType ) { // Just get rid of the name we allocated for the directory FREE ( cddaNodePtr->u.directory.name, M_TEMP ); cddaNodePtr->u.directory.name = NULL; } else if ( cddaNodePtr->nodeType == kAppleCDDATrackType ) { if ( cddaNodePtr->u.file.nodeInfoPtr != NULL ) { // Remove this vnode from our list cddaNodePtr->u.file.nodeInfoPtr->vNodePtr = NULL; cddaNodePtr->u.file.nodeInfoPtr = NULL; } } else if ( cddaNodePtr->nodeType == kAppleCDDXMLFileType ) { FREE ( cddaNodePtr->u.xmlFile.fileDataPtr, M_TEMP ); cddaNodePtr->u.xmlFile.fileDataPtr = NULL; cddaNodePtr->u.xmlFile.fileSize = 0; } // Free memory associated with our filesystem's internal data FREE ( vNodePtr->v_data, M_TEMP ); vNodePtr->v_data = NULL; } return ( 0 ); } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // CreateNewCDDAFile - This routine is responsible for creating new // files //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ int CreateNewCDDAFile ( struct mount * mountPtr, UInt32 nodeID, AppleCDDANodeInfoPtr nodeInfoPtr, struct proc * procPtr, struct vnode ** vNodeHandle ) { int result = 0; struct vnode * vNodePtr = NULL; AppleCDDANodePtr cddaNodePtr = NULL; AppleCDDANodePtr parentCDDANodePtr = NULL; AppleCDDAMountPtr cddaMountPtr = NULL; DebugAssert ( ( mountPtr != NULL ) ); DebugAssert ( ( nodeInfoPtr != NULL ) ); DebugAssert ( ( procPtr != NULL ) ); DebugAssert ( ( vNodeHandle != NULL ) ); result = CreateNewCDDANode ( mountPtr, nodeID, procPtr, &vNodePtr ); if ( result != 0 ) { DebugLog ( ( "Error = %d returned from CreatNewCDDANode\n", result ) ); return result; } cddaNodePtr = VTOCDDA ( vNodePtr ); cddaMountPtr = VFSTOCDDA ( mountPtr ); parentCDDANodePtr = VTOCDDA ( cddaMountPtr->root ); DebugAssert ( ( cddaNodePtr != NULL ) ); DebugAssert ( ( cddaMountPtr != NULL ) ); DebugAssert ( ( parentCDDANodePtr != NULL ) ); // Initialize the relevant vnode fields vNodePtr->v_type = VREG; // Fill in the miscellaneous fields for the cddaNode cddaNodePtr->u.file.aiffHeader = BuildCDAIFFHeader ( nodeInfoPtr->numBytes ); cddaNodePtr->nodeType = kAppleCDDATrackType; cddaNodePtr->blockDeviceVNodePtr = parentCDDANodePtr->blockDeviceVNodePtr; // Set the back pointer cddaNodePtr->u.file.nodeInfoPtr = nodeInfoPtr; DebugLog ( ( "LBA of %d = %ld.\n", cddaNodePtr->nodeID, nodeInfoPtr->LBA ) ); // Init the UBC info if ( UBCINFOMISSING ( vNodePtr ) || UBCINFORECLAIMED ( vNodePtr ) ) { ubc_info_init ( vNodePtr ); } // stuff the vNode in *vNodeHandle = vNodePtr; return 0; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // CreateNewXMLFile - This routine is responsible for creating the ".cdid" // file which has the unique disc ID string //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ int CreateNewXMLFile ( struct mount * mountPtr, struct proc * procPtr, UInt32 xmlFileSize, UInt8 * xmlData, struct vnode ** vNodeHandle ) { int result = 0; struct vnode * vNodePtr = NULL; AppleCDDANodePtr cddaNodePtr = NULL; AppleCDDANodePtr parentCDDANodePtr = NULL; AppleCDDAMountPtr cddaMountPtr = NULL; DebugAssert ( ( mountPtr != NULL ) ); DebugAssert ( ( procPtr != NULL ) ); DebugAssert ( ( vNodeHandle != NULL ) ); result = CreateNewCDDANode ( mountPtr, kAppleCDDAXMLFileID, procPtr, &vNodePtr ); if ( result != 0 ) { DebugLog ( ( "Error = %d returned from CreatNewCDDANode\n", result ) ); return result; } cddaNodePtr = VTOCDDA ( vNodePtr ); cddaMountPtr = VFSTOCDDA ( mountPtr ); parentCDDANodePtr = VTOCDDA ( cddaMountPtr->root ); DebugAssert ( ( cddaNodePtr != NULL ) ); DebugAssert ( ( cddaMountPtr != NULL ) ); DebugAssert ( ( parentCDDANodePtr != NULL ) ); // Initialize the relevant vnode fields vNodePtr->v_type = VREG; // Fill in the miscellaneous fields for the cddaNode cddaNodePtr->nodeType = kAppleCDDXMLFileType; cddaNodePtr->blockDeviceVNodePtr = parentCDDANodePtr->blockDeviceVNodePtr; // Point the xmlData to the correct place cddaNodePtr->u.xmlFile.fileDataPtr = xmlData; cddaNodePtr->u.xmlFile.fileSize = xmlFileSize; #if 0 { UInt32 count; // Let's see if we got the right data mapped in for ( count = 0; count < xmlFileSize; count = count + 8 ) { DebugLog ( ( "%x:%x:%x:%x %x:%x:%x:%x\n", xmlData[count], xmlData[count+1], xmlData[count+2], xmlData[count+3], xmlData[count+4], xmlData[count+5], xmlData[count+6], xmlData[count+7] ) ); } DebugLog ( ( "\n" ) ); } #endif // Init the UBC info if ( UBCINFOMISSING ( vNodePtr ) || UBCINFORECLAIMED ( vNodePtr ) ) { ubc_info_init ( vNodePtr ); } // stuff the vNode in *vNodeHandle = vNodePtr; return 0; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // CreateNewCDDADirectory - This routine is responsible for creating new // directories //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ int CreateNewCDDADirectory ( struct mount * mountPtr, const char * name, UInt32 nodeID, struct proc * procPtr, struct vnode ** vNodeHandle ) { int result = 0; struct vnode * vNodePtr = NULL; AppleCDDANodePtr cddaNodePtr = NULL; DebugAssert ( ( mountPtr != NULL ) ); DebugAssert ( ( procPtr != NULL ) ); DebugAssert ( ( vNodeHandle != NULL ) ); result = CreateNewCDDANode ( mountPtr, nodeID, procPtr, &vNodePtr ); if ( result != 0 ) { DebugLog ( ( "Error = %d returned from CreatNewCDDANode\n", result ) ); return result; } cddaNodePtr = VTOCDDA ( vNodePtr ); DebugAssert ( ( cddaNodePtr != NULL ) ); // Initialize the relevant vnode fields vNodePtr->v_type = VDIR; // Set up the directory-specific fields cddaNodePtr->nodeType = kAppleCDDADirectoryType; cddaNodePtr->u.directory.directorySize = 0; cddaNodePtr->u.directory.entryCount = kNumberOfFakeDirEntries; // ".", "..", and ".TOC.plist" name = name + 8; // Allocate memory for the directory name MALLOC ( cddaNodePtr->u.directory.name, char *, strlen ( name ) + 1, M_TEMP, M_WAITOK ); // Copy the name over strcpy ( cddaNodePtr->u.directory.name, name ); // stuff the vNode in *vNodeHandle = vNodePtr; return 0; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // IsAudioTrack - Checks the arguments passed in to find out if specified // track is audio or not //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ boolean_t IsAudioTrack ( const SubQTOCInfoPtr trackDescriptorPtr ) { DebugAssert ( ( trackDescriptorPtr != NULL ) ); // Check to make sure the point is between 1 and 99 (inclusive) if ( trackDescriptorPtr->point < 100 && trackDescriptorPtr->point > 0 ) { // Do we have digital data? if ( ( trackDescriptorPtr->control & kDigitalDataMask ) == 0 ) { // Found an audio track return TRUE; } } return FALSE; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // CalculateSize - Calculate the file size based on number of frames // (i.e. blocks) in the track //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ UInt32 CalculateSize ( const QTOCDataFormat10Ptr TOCDataPtr, UInt32 trackDescriptorOffset, UInt32 currentA2Offset ) { UInt32 size = 0; UInt32 offset = 0; UInt32 numberOfDescriptors = 0; UInt32 nextOffset = 0; SubQTOCInfoPtr trackDescriptorPtr = NULL; SubQTOCInfoPtr nextTrackDescriptorPtr = NULL; DebugLog ( ( "CalculateSize: Entering...\n" ) ); DebugAssert ( ( TOCDataPtr != NULL ) ); // Find the number of descriptors numberOfDescriptors = CalculateNumberOfDescriptors ( TOCDataPtr ); // Get the correct track descriptor trackDescriptorPtr = &TOCDataPtr->trackDescriptors[trackDescriptorOffset]; // Are we past the total number of descriptors in TOC? if ( trackDescriptorOffset + 1 >= numberOfDescriptors ) { // yes, so set the descriptor to the last leadout descriptor we hit nextTrackDescriptorPtr = &TOCDataPtr->trackDescriptors[currentA2Offset]; } else { // no, so set the descriptor to the next entry in the TOC nextTrackDescriptorPtr = &TOCDataPtr->trackDescriptors[trackDescriptorOffset + 1]; // Are we past the end of the session? if ( trackDescriptorPtr->sessionNumber != nextTrackDescriptorPtr->sessionNumber || !IsAudioTrack ( nextTrackDescriptorPtr ) ) { // yes, so set the descriptor to the last leadout descriptor we hit nextTrackDescriptorPtr = &TOCDataPtr->trackDescriptors[currentA2Offset]; } } // Calculate the LBAs for both tracks offset = CalculateLBA ( trackDescriptorPtr ); nextOffset = CalculateLBA ( nextTrackDescriptorPtr ); // Multiply number of blocks by block size and add the header size = ( ( nextOffset - offset ) * kPhysicalMediaBlockSize ) + sizeof ( CDAIFFHeader ); DebugLog ( ( "CalculateSize: size = %ld.\n", size ) ); DebugLog ( ( "CalculateSize: exiting...\n" ) ); return size; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // FindName - Parses the names data that gets passed in to the // filesystem, looking for the specified track's name. // All names look like the following packed structure: // // | 1 byte | 1 byte | number of bytes in 2nd byte | // Track # size of String String for Name // // Track # of zero corresponds to the album name (the mount point name). //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ int FindName ( struct mount * mountPtr, UInt8 trackNumber, char ** name, UInt8 * nameSize ) { AppleCDDAMountPtr cddaMountPtr = NULL; UInt8 * ptr = NULL; UInt8 length = 0; DebugLog ( ( "FindName: entering\n" ) ); DebugLog ( ( "trackNumber = %d\n" ) ); DebugAssert ( ( mountPtr != NULL ) ); DebugAssert ( ( name != NULL ) ); DebugAssert ( ( nameSize != NULL ) ); cddaMountPtr = VFSTOCDDA ( mountPtr ); DebugLog ( ( "cddaMountPtr->nameDataSize = %ld\n", cddaMountPtr->nameDataSize ) ); ptr = cddaMountPtr->nameData; if ( ptr == NULL ) { DebugLog ( ( "cddaMountPtr->nameData is NULL" ) ); return ENOENT; } do { DebugLog ( ( "*ptr = %d\n", *ptr ) ); if ( *ptr == trackNumber ) { char mylocalname[512]; DebugLog ( ( "Found track = %d\n", trackNumber ) ); *nameSize = ptr[1]; *name = &ptr[2]; bcopy ( &ptr[2], mylocalname, *nameSize ); mylocalname[*nameSize] = 0; DebugLog ( ( "NameSize = %d\n", *nameSize ) ); DebugLog ( ( "Name = %s\n", mylocalname ) ); break; } else { length = ptr[1]; DebugLog ( ( "Didn't find it, keep looking\n" ) ); ptr = &ptr[length + 2]; } } while ( ptr < ( cddaMountPtr->nameData + cddaMountPtr->nameDataSize ) ); DebugLog ( ( "FindName: exiting\n" ) ); return 0; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ParseTOC - Parses the TOC to find audio tracks. It figures out which // tracks are audio and what their offsets are and fills in the // cddaNode structures associated with each vnode //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ SInt32 ParseTOC ( struct mount * mountPtr, UInt32 numTracks, UInt32 xmlFileSize, UInt8 * xmlData, struct proc * theProc ) { QTOCDataFormat10Ptr TOCDataPtr = NULL; SubQTOCInfoPtr trackDescriptorPtr = NULL; AppleCDDAMountPtr cddaMountPtr = NULL; AppleCDDANodeInfoPtr nodeInfoPtr = NULL; AppleCDDADirectoryNodePtr rootDirNodePtr = NULL; OSStatus error = 0; UInt16 numberOfDescriptors = 0; char * ioBSDNamePtr = NULL; UInt32 currentA2Offset = 0; UInt32 currentOffset = 0; DebugLog ( ( "ParseTOC: Entering...\n" ) ); DebugAssert ( ( mountPtr != NULL ) ); DebugAssert ( ( theProc != NULL ) ); cddaMountPtr = VFSTOCDDA ( mountPtr ); rootDirNodePtr = &( ( VTOCDDA ( cddaMountPtr->root ) )->u.directory ); ioBSDNamePtr = mountPtr->mnt_stat.f_mntfromname; DebugAssert ( ( cddaMountPtr != NULL ) ); DebugAssert ( ( rootDirNodePtr != NULL ) ); DebugAssert ( ( ioBSDNamePtr != NULL ) ); // Get the data from the registry entry TOCDataPtr = CreateBufferFromIORegistry ( mountPtr ); if ( TOCDataPtr != NULL ) { // Generate the xml TOC file for this disc error = CreateNewXMLFile ( mountPtr, theProc, xmlFileSize, xmlData, &cddaMountPtr->xmlFileVNodePtr ); if ( error != 0 ) { DebugLog ( ( "Error = %d creating xml file.\n", error ) ); goto Exit; } // calculate number of track descriptors numberOfDescriptors = CalculateNumberOfDescriptors ( TOCDataPtr ); DebugLog ( ( "Number of descriptors = %d\n", numberOfDescriptors ) ); if ( numberOfDescriptors <= 0 ) { AppleCDDANodePtr cddaNodePtr; // This is bad...no track descriptors, time to bail error = EINVAL; cddaNodePtr = VTOCDDA ( cddaMountPtr->xmlFileVNodePtr ); // Don't forget to release memory for xmlFile FREE ( cddaNodePtr->u.xmlFile.fileDataPtr, M_TEMP ); cddaNodePtr->u.xmlFile.fileDataPtr = NULL; cddaNodePtr->u.xmlFile.fileSize = 0; goto Exit; } trackDescriptorPtr = TOCDataPtr->trackDescriptors; while ( numberOfDescriptors > 0 && rootDirNodePtr->entryCount < ( numTracks + kNumberOfFakeDirEntries ) ) { if ( trackDescriptorPtr->point == 0xA2 ) { // Set the a2 offset when we find an a2 point currentA2Offset = currentOffset; } // Is this an audio track? if ( IsAudioTrack ( trackDescriptorPtr ) ) { // Make this easier to read by getting a pointer to the nodeInfo nodeInfoPtr = &cddaMountPtr->nodeInfoArrayPtr[rootDirNodePtr->entryCount - kNumberOfFakeDirEntries]; // Copy this trackDescriptor into the AppleCDDANodeInfo array nodeInfoPtr->trackDescriptor = *trackDescriptorPtr; // Get the LogicalBlockAddress and number of bytes in the track nodeInfoPtr->LBA = CalculateLBA ( trackDescriptorPtr ); nodeInfoPtr->numBytes = CalculateSize ( TOCDataPtr, currentOffset, currentA2Offset ); // Add this node's size to the root directory's directorySize field rootDirNodePtr->directorySize += nodeInfoPtr->numBytes; // Increment the number of audio tracks rootDirNodePtr->entryCount++; ( void ) BuildTrackName ( mountPtr, nodeInfoPtr ); DebugLog ( ( "LBA of %d = %ld.\n", trackDescriptorPtr->point, nodeInfoPtr->LBA ) ); } // Advance the pointers and decrement the count trackDescriptorPtr++; numberOfDescriptors--; currentOffset++; } if ( numberOfDescriptors != 0 && rootDirNodePtr->entryCount == ( numTracks + kNumberOfFakeDirEntries ) ) { // Oops...the parsing routine in userland must've screwed up DebugLog ( ( "ParseTOC: userland utility sent wrong number of audio tracks in at mount time.\n" ) ); } } else { // Couldn't parse the TOC, so return an error return ENOMEM; } Exit: if ( TOCDataPtr != NULL ) { // Free the buffer allocated earlier DisposeBufferFromIORegistry ( TOCDataPtr ); } DebugLog ( ( "ParseTOC: exiting...\n" ) ); return error; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // BuildTrackName - This routine is responsible for building a track // name based on its number //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ int BuildTrackName ( struct mount * mountPtr, AppleCDDANodeInfoPtr nodeInfoPtr ) { UInt8 offset = 0; UInt8 trackNumber = 0; char * name; UInt8 nameSize; int error; UInt8 numberOfPadBytes = 2; DebugLog ( ( "BuildTrackName: entering.\n" ) ); DebugAssert ( ( nodeInfoPtr != NULL ) ); // Get the track number for which to find the name trackNumber = nodeInfoPtr->trackDescriptor.point; // Find the name error = FindName ( mountPtr, trackNumber, &name, &nameSize ); if ( error != 0 ) { DebugLog ( ( "cddafs : FindName returned error = %d\n", error ) ); // Buffer copied in was formatted incorrectly. We'll just use // track numbers on this CD. } if ( nodeInfoPtr->trackDescriptor.point > 9 ) { numberOfPadBytes++; } // Set the size of the name nodeInfoPtr->nameSize = nameSize + strlen ( gFileSuffix ) + numberOfPadBytes; // If we got here, then we have a valid track and the nodeInfoArrayPtr points to our // offset into the array. So, MALLOC the name here MALLOC ( nodeInfoPtr->name, char *, nodeInfoPtr->nameSize + 1, M_TEMP, M_WAITOK ); if ( nodeInfoPtr->trackDescriptor.point > 9 ) { nodeInfoPtr->name[offset++] = ( nodeInfoPtr->trackDescriptor.point / 10 ) + kASCIINumberZero; } nodeInfoPtr->name[offset++] = ( nodeInfoPtr->trackDescriptor.point % 10 ) + kASCIINumberZero; nodeInfoPtr->name[offset++] = ' '; // Copy the name and the suffix to the name ptr. bcopy ( name, &nodeInfoPtr->name[offset], nameSize ); offset += nameSize; bcopy ( gFileSuffix, &nodeInfoPtr->name[offset], strlen ( gFileSuffix ) ); offset += strlen ( gFileSuffix ); // Don't forget NULL byte nodeInfoPtr->name[offset] = 0; DebugLog ( ( "BuildTrackName: fileName = %s\n", nodeInfoPtr->name ) ); return 0; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // CalculateNumberOfDescriptors - Calculate the number of SubQTOCInfo entries // in the given TOC //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ UInt32 CalculateNumberOfDescriptors ( const QTOCDataFormat10Ptr TOCDataPtr ) { UInt32 numberOfDescriptors = 0; UInt32 length = 0; DebugLog ( ( "CalculateNumberOfDescriptors: Entering...\n" ) ); DebugAssert ( ( TOCDataPtr != NULL ) ); // Get the length of the TOC length = TOCDataPtr->TOCDataLength; // Remove the first and last session numbers so all we are left with are track descriptors length -= ( sizeof ( TOCDataPtr->firstSessionNumber ) + sizeof ( TOCDataPtr->lastSessionNumber ) ); // Divide the length by the size of a single track descriptor to get total number numberOfDescriptors = length / ( sizeof ( SubQTOCInfo ) ); DebugLog ( ( "CalculateNumberOfDescriptors: exiting...\n" ) ); return numberOfDescriptors; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // CalculateLBA - Convert the frames offset of the file (from the TOC) to // the LBA of the device // // NB: this is a workaround because the first 2 seconds of a CD are unreadable // and defined as off-limits. So we convert our absolute MSF to an actual // logical block which can be addressed through the BSD layer. //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ UInt32 CalculateLBA ( SubQTOCInfoPtr trackDescriptorPtr ) { DebugAssert ( ( trackDescriptorPtr != NULL ) ); // Simply convert MSF to LBA return ( ( trackDescriptorPtr->PMSF.startPosition.minutes * kSecondsPerMinute + trackDescriptorPtr->PMSF.startPosition.seconds ) * kFramesPerSecond + trackDescriptorPtr->PMSF.startPosition.frames - kMSFToLBA ); } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // CalculateAttributeBlockSize - Calculates the size of the attribute // block //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ int CalculateAttributeBlockSize ( struct attrlist * attrlist ) { int size; attrgroup_t a; #if ( ( ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | ATTR_CMN_OBJTYPE | \ ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | ATTR_CMN_OBJPERMANENTID | ATTR_CMN_PAROBJID | \ ATTR_CMN_SCRIPT | ATTR_CMN_CRTIME | ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | \ ATTR_CMN_ACCTIME | ATTR_CMN_BKUPTIME | ATTR_CMN_FNDRINFO | ATTR_CMN_OWNERID | \ ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK | ATTR_CMN_NAMEDATTRCOUNT | ATTR_CMN_NAMEDATTRLIST| \ ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS ) != ATTR_CMN_VALIDMASK ) #error CalculateAttributeBlockSize: Missing bits in common mask computation! #endif DebugAssert ( ( attrlist->commonattr & ~ATTR_CMN_VALIDMASK ) == 0 ); #if ( ( ATTR_VOL_FSTYPE | ATTR_VOL_SIGNATURE | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE | \ ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION | ATTR_VOL_ALLOCATIONCLUMP | ATTR_VOL_IOBLOCKSIZE | \ ATTR_VOL_OBJCOUNT | ATTR_VOL_FILECOUNT | ATTR_VOL_DIRCOUNT | ATTR_VOL_MAXOBJCOUNT | \ ATTR_VOL_MOUNTPOINT | ATTR_VOL_NAME | ATTR_VOL_MOUNTFLAGS | ATTR_VOL_INFO | \ ATTR_VOL_MOUNTEDDEVICE | ATTR_VOL_ENCODINGSUSED | ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES ) != ATTR_VOL_VALIDMASK ) #error CalculateAttributeBlockSize: Missing bits in volume mask computation! #endif DebugAssert ( ( attrlist->volattr & ~ATTR_VOL_VALIDMASK ) == 0 ); #if ( ( ATTR_DIR_LINKCOUNT | ATTR_DIR_ENTRYCOUNT | ATTR_DIR_MOUNTSTATUS ) != ATTR_DIR_VALIDMASK ) #error CalculateAttributeBlockSize: Missing bits in directory mask computation! #endif DebugAssert ( ( attrlist->dirattr & ~ATTR_DIR_VALIDMASK ) == 0 ); #if ( ( ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE | ATTR_FILE_ALLOCSIZE | ATTR_FILE_IOBLOCKSIZE | \ ATTR_FILE_CLUMPSIZE | ATTR_FILE_DEVTYPE | ATTR_FILE_FILETYPE | ATTR_FILE_FORKCOUNT | \ ATTR_FILE_FORKLIST | ATTR_FILE_DATALENGTH | ATTR_FILE_DATAALLOCSIZE | ATTR_FILE_DATAEXTENTS | \ ATTR_FILE_RSRCLENGTH | ATTR_FILE_RSRCALLOCSIZE | ATTR_FILE_RSRCEXTENTS ) != ATTR_FILE_VALIDMASK ) #error CalculateAttributeBlockSize: Missing bits in file mask computation! #endif DebugAssert ( ( attrlist->fileattr & ~ATTR_FILE_VALIDMASK ) == 0 ); #if ( ( ATTR_FORK_TOTALSIZE | ATTR_FORK_ALLOCSIZE ) != ATTR_FORK_VALIDMASK ) #error CalculateAttributeBlockSize: Missing bits in fork mask computation! #endif DebugAssert ( ( attrlist->forkattr & ~ATTR_FORK_VALIDMASK ) == 0 ); size = 0; if ( ( a = attrlist->commonattr ) != 0 ) { DebugLog ( ( "Common attributes wanted\n" ) ); if ( a & ATTR_CMN_NAME ) size += sizeof ( struct attrreference ); if ( a & ATTR_CMN_DEVID ) size += sizeof ( dev_t ); if ( a & ATTR_CMN_FSID ) size += sizeof ( fsid_t ); if ( a & ATTR_CMN_OBJTYPE ) size += sizeof ( fsobj_type_t ); if ( a & ATTR_CMN_OBJTAG ) size += sizeof ( fsobj_tag_t ); if ( a & ATTR_CMN_OBJID ) size += sizeof ( fsobj_id_t ); if ( a & ATTR_CMN_OBJPERMANENTID ) size += sizeof ( fsobj_id_t ); if ( a & ATTR_CMN_PAROBJID ) size += sizeof( fsobj_id_t ); if ( a & ATTR_CMN_SCRIPT ) size += sizeof ( text_encoding_t ); if ( a & ATTR_CMN_CRTIME ) size += sizeof ( struct timespec ); if ( a & ATTR_CMN_MODTIME ) size += sizeof ( struct timespec ); if ( a & ATTR_CMN_CHGTIME ) size += sizeof ( struct timespec ); if ( a & ATTR_CMN_ACCTIME ) size += sizeof ( struct timespec ); if ( a & ATTR_CMN_BKUPTIME ) size += sizeof ( struct timespec ); if ( a & ATTR_CMN_FNDRINFO ) size += 32 * sizeof ( UInt8 ); if ( a & ATTR_CMN_OWNERID ) size += sizeof ( uid_t ); if ( a & ATTR_CMN_GRPID ) size += sizeof ( gid_t ); if ( a & ATTR_CMN_ACCESSMASK ) size += sizeof ( UInt32 ); if ( a & ATTR_CMN_NAMEDATTRCOUNT ) size += sizeof ( UInt32 ); if ( a & ATTR_CMN_NAMEDATTRLIST ) size += sizeof ( struct attrreference ); if ( a & ATTR_CMN_FLAGS ) size += sizeof ( UInt32 ); if ( a & ATTR_CMN_USERACCESS ) size += sizeof ( UInt32 ); } if ( ( a = attrlist ->volattr ) != 0 ) { DebugLog ( ( "Volume attributes wanted\n" ) ); if ( a & ATTR_VOL_FSTYPE ) size += sizeof ( UInt32 ); if ( a & ATTR_VOL_SIGNATURE ) size += sizeof ( UInt32 ); if ( a & ATTR_VOL_SIZE ) size += sizeof ( off_t ); if ( a & ATTR_VOL_SPACEFREE ) size += sizeof ( off_t ); if ( a & ATTR_VOL_SPACEAVAIL ) size += sizeof ( off_t ); if ( a & ATTR_VOL_MINALLOCATION ) size += sizeof ( off_t ); if ( a & ATTR_VOL_ALLOCATIONCLUMP ) size += sizeof ( off_t ); if ( a & ATTR_VOL_IOBLOCKSIZE ) size += sizeof ( UInt32 ); if ( a & ATTR_VOL_OBJCOUNT ) size += sizeof ( UInt32 ); if ( a & ATTR_VOL_FILECOUNT ) size += sizeof ( UInt32 ); if ( a & ATTR_VOL_DIRCOUNT ) size += sizeof ( UInt32 ); if ( a & ATTR_VOL_MAXOBJCOUNT ) size += sizeof ( UInt32 ); if ( a & ATTR_VOL_MOUNTPOINT ) size += sizeof ( struct attrreference ); if ( a & ATTR_VOL_NAME ) size += sizeof ( struct attrreference ); if ( a & ATTR_VOL_MOUNTFLAGS ) size += sizeof ( UInt32 ); if ( a & ATTR_VOL_MOUNTEDDEVICE ) size += sizeof ( struct attrreference ); if ( a & ATTR_VOL_ENCODINGSUSED ) size += sizeof ( UInt64 ); if ( a & ATTR_VOL_CAPABILITIES ) size += sizeof ( vol_capabilities_attr_t ); if ( a & ATTR_VOL_ATTRIBUTES ) size += sizeof ( vol_attributes_attr_t ); } if ( ( a = attrlist->dirattr ) != 0 ) { DebugLog ( ( "Directory attributes wanted\n" ) ); if ( a & ATTR_DIR_LINKCOUNT ) size += sizeof ( UInt32 ); if ( a & ATTR_DIR_ENTRYCOUNT ) size += sizeof ( UInt32 ); if ( a & ATTR_DIR_MOUNTSTATUS ) size += sizeof ( UInt32 ); } if ( ( a = attrlist->fileattr ) != 0 ) { DebugLog ( ( "File attributes wanted\n" ) ); if ( a & ATTR_FILE_LINKCOUNT ) size += sizeof ( UInt32 ); if ( a & ATTR_FILE_TOTALSIZE ) size += sizeof ( off_t ); if ( a & ATTR_FILE_ALLOCSIZE ) size += sizeof ( off_t ); if ( a & ATTR_FILE_IOBLOCKSIZE ) size += sizeof ( size_t ); if ( a & ATTR_FILE_CLUMPSIZE ) size += sizeof ( off_t ); if ( a & ATTR_FILE_DEVTYPE ) size += sizeof ( UInt32 ); if ( a & ATTR_FILE_FILETYPE ) size += sizeof ( UInt32 ); if ( a & ATTR_FILE_FORKCOUNT ) size += sizeof ( UInt32 ); if ( a & ATTR_FILE_FORKLIST ) size += sizeof ( struct attrreference ); if ( a & ATTR_FILE_DATALENGTH ) size += sizeof ( off_t ); if ( a & ATTR_FILE_DATAALLOCSIZE ) size += sizeof ( off_t ); if ( a & ATTR_FILE_DATAEXTENTS ) size += sizeof ( extentrecord ); if ( a & ATTR_FILE_RSRCLENGTH ) size += sizeof ( off_t ); if ( a & ATTR_FILE_RSRCALLOCSIZE ) size += sizeof ( off_t ); if ( a & ATTR_FILE_RSRCEXTENTS ) size += sizeof ( extentrecord ); } if ( ( a = attrlist->forkattr ) != 0 ) { DebugLog ( ( "Fork attributes wanted\n" ) ); if ( a & ATTR_FORK_TOTALSIZE ) size += sizeof ( off_t ); if ( a & ATTR_FORK_ALLOCSIZE ) size += sizeof ( off_t ); } return size; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // PackVolumeAttributes - Packs the volume attributes //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void PackVolumeAttributes ( struct attrlist * attrListPtr, AppleCDDANodePtr cddaNodePtr, void ** attrbufHandle, void ** varbufHandle ) { void * attrbufptr; void * varbufptr; attrgroup_t a; UInt32 attrlength; DebugLog ( ( "PackVolumeAttributes called\n" ) ); attrbufptr = *attrbufHandle; varbufptr = *varbufHandle; if ( ( a = attrListPtr->commonattr ) != 0 ) { if ( a & ATTR_CMN_NAME ) { DebugLog ( ( "ATTR_CMN_NAME : %s\n", cddaNodePtr->u.directory.name ) ); attrlength = strlen ( cddaNodePtr->u.directory.name ) + 1; ( ( struct attrreference * ) attrbufptr )->attr_dataoffset = ( UInt8 * ) varbufptr - ( UInt8 * ) attrbufptr; ( ( struct attrreference *) attrbufptr )->attr_length = attrlength; ( void ) strncpy ( ( UInt8 * ) varbufptr, cddaNodePtr->u.directory.name, attrlength ); /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */ ( UInt8 * ) varbufptr += attrlength + ( ( 4 - ( attrlength & 3 ) ) & 3 ); ++( ( struct attrreference * ) attrbufptr ); } if ( a & ATTR_CMN_DEVID ) { DebugLog ( ( "ATTR_CMN_DEVID : %ld\n", *( dev_t * ) &( CDDATOV ( cddaNodePtr )->v_mount->mnt_stat.f_fsid ) ) ); *( ( dev_t * ) attrbufptr )++ = *( dev_t * ) &( CDDATOV ( cddaNodePtr )->v_mount->mnt_stat.f_fsid ); } if ( a & ATTR_CMN_FSID ) { DebugLog ( ( "ATTR_CMN_FSID : %d\n", CDDATOV ( cddaNodePtr )->v_mount->mnt_stat.f_fsid ) ); *( ( fsid_t * ) attrbufptr )++ = CDDATOV ( cddaNodePtr )->v_mount->mnt_stat.f_fsid; } if ( a & ATTR_CMN_OBJTYPE ) { DebugLog ( ( "ATTR_CMN_OBJTYPE : %d\n", 0 ) ); *( ( fsobj_type_t * ) attrbufptr )++ = 0; } if ( a & ATTR_CMN_OBJTAG ) { DebugLog ( ( "ATTR_CMN_OBJTAG : %d\n", VT_CDDA ) ); *( ( fsobj_tag_t * ) attrbufptr )++ = VT_CDDA; } if ( a & ATTR_CMN_OBJID ) { DebugLog ( ( "ATTR_CMN_OBJID : fid_objno = %d, fid_generation = %d\n", 0, 0 ) ); ( ( fsobj_id_t * ) attrbufptr )->fid_objno = 0; ( ( fsobj_id_t * ) attrbufptr )->fid_generation = 0; ++( ( fsobj_id_t * ) attrbufptr ); } if ( a & ATTR_CMN_OBJPERMANENTID ) { DebugLog ( ( "ATTR_CMN_OBJPERMANENTID : fid_objno = %d, fid_generation = %d\n", 0, 0 ) ); ( ( fsobj_id_t * ) attrbufptr )->fid_objno = 0; ( ( fsobj_id_t * ) attrbufptr )->fid_generation = 0; ++( ( fsobj_id_t * ) attrbufptr ); } if ( a & ATTR_CMN_PAROBJID ) { DebugLog ( ( "ATTR_CMN_PAROBJID : fid_objno = %d, fid_generation = %d\n", 0, 0 ) ); ( ( fsobj_id_t * ) attrbufptr )->fid_objno = 0; ( ( fsobj_id_t * ) attrbufptr )->fid_generation = 0; ++( ( fsobj_id_t * ) attrbufptr ); } if ( a & ATTR_CMN_SCRIPT ) { DebugLog ( ( "ATTR_CMN_SCRIPT\n" ) ); *( ( text_encoding_t * ) attrbufptr )++ = 0; } if ( a & ATTR_CMN_CRTIME ) { DebugLog ( ( "ATTR_CMN_CRTIME\n" ) ); *( ( struct timespec * ) attrbufptr )++ = VFSTOCDDA ( cddaNodePtr->vNodePtr->v_mount )->mountTime; } if ( a & ATTR_CMN_MODTIME ) { DebugLog ( ( "ATTR_CMN_MODTIME\n" ) ); *( ( struct timespec * ) attrbufptr )++ = VFSTOCDDA ( cddaNodePtr->vNodePtr->v_mount )->mountTime; } if ( a & ATTR_CMN_CHGTIME ) { DebugLog ( ( "ATTR_CMN_CHGTIME\n" ) ); *( ( struct timespec * ) attrbufptr )++ = cddaNodePtr->lastModTime; } if ( a & ATTR_CMN_ACCTIME ) { DebugLog ( ( "ATTR_CMN_ACCTIME\n" ) ); *( ( struct timespec * ) attrbufptr )++ = cddaNodePtr->accessTime; } if ( a & ATTR_CMN_BKUPTIME ) { DebugLog ( ( "ATTR_CMN_BKUPTIME\n" ) ); ( ( struct timespec * ) attrbufptr )->tv_sec = 0; ( ( struct timespec * ) attrbufptr )->tv_nsec = 0; ++( ( struct timespec * ) attrbufptr ); } if ( a & ATTR_CMN_FNDRINFO ) { DebugLog ( ( "ATTR_CMN_FNDRINFO\n" ) ); bzero ( attrbufptr, 32 * sizeof ( UInt8 ) ); ( UInt8 * ) attrbufptr += 32 * sizeof ( UInt8 ); } if ( a & ATTR_CMN_OWNERID ) { DebugLog ( ( "ATTR_CMN_OWNERID\n" ) ); *( ( uid_t * ) attrbufptr )++ = kUnknownUserID; } if ( a & ATTR_CMN_GRPID ) { DebugLog ( ( "ATTR_CMN_GRPID\n" ) ); *( ( gid_t * ) attrbufptr )++ = kUnknownGroupID; } if ( a & ATTR_CMN_ACCESSMASK ) { UInt32 access = S_IRUSR | S_IRGRP | S_IROTH; if ( cddaNodePtr->vNodePtr->v_flag & VROOT ) access |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; DebugLog ( ( "ATTR_CMN_ACCESSMASK\n" ) ); *( ( UInt32 * ) attrbufptr )++ = access; } if ( a & ATTR_CMN_FLAGS ) { DebugLog ( ( "ATTR_CMN_FLAGS\n" ) ); *( ( UInt32 * ) attrbufptr )++ = 0; } if ( a & ATTR_CMN_USERACCESS ) { UInt32 permissions = R_OK; DebugLog ( ( "ATTR_CMN_USERACCESS\n" ) ); if ( cddaNodePtr->vNodePtr->v_flag & VROOT ) permissions |= X_OK; *( ( UInt32 * ) attrbufptr )++ = permissions; } } if ( ( a = attrListPtr->volattr ) != 0 ) { off_t blocksize = ( off_t ) kAppleCDDABlockSize; if ( a & ATTR_VOL_FSTYPE ) { DebugLog ( ( "ATTR_VOL_FSTYPE : %d\n", cddaNodePtr->vNodePtr->v_mount->mnt_vfc->vfc_typenum ) ); *( ( UInt32 * ) attrbufptr )++ = cddaNodePtr->vNodePtr->v_mount->mnt_vfc->vfc_typenum; } if ( a & ATTR_VOL_SIGNATURE ) { DebugLog ( ( "ATTR_VOL_SIGNATURE : 0x%04x\n", 0x4A48 ) ); *( ( UInt32 * ) attrbufptr )++ = ( UInt32 ) 0x4A48; } if ( a & ATTR_VOL_SIZE ) { DebugLog ( ( "ATTR_VOL_SIZE : %d\n", cddaNodePtr->u.directory.directorySize ) ); *( ( off_t * ) attrbufptr )++ = cddaNodePtr->u.directory.directorySize; } if ( a & ATTR_VOL_SPACEFREE ) { DebugLog ( ( "ATTR_VOL_SPACEFREE : %d\n", 0 ) ); *( ( off_t * ) attrbufptr )++ = 0; } if ( a & ATTR_VOL_SPACEAVAIL ) { DebugLog ( ( "ATTR_VOL_SPACEAVAIL : %d\n", 0 ) ); *( ( off_t * ) attrbufptr )++ = 0; } if ( a & ATTR_VOL_MINALLOCATION ) { DebugLog ( ( "ATTR_VOL_MINALLOCATION : %d\n", blocksize ) ); *( ( off_t *) attrbufptr )++ = blocksize; } if ( a & ATTR_VOL_ALLOCATIONCLUMP ) { DebugLog ( ( "ATTR_VOL_ALLOCATIONCLUMP : %d\n", blocksize ) ); *( ( off_t *) attrbufptr )++ = blocksize; } if ( a & ATTR_VOL_IOBLOCKSIZE ) { DebugLog ( ( "ATTR_VOL_IOBLOCKSIZE : %d\n", blocksize ) ); *( ( off_t *) attrbufptr )++ = blocksize; } if ( a & ATTR_VOL_OBJCOUNT ) { DebugLog ( ( "ATTR_VOL_OBJCOUNT : %d\n", 0 ) ); *( ( UInt32 * ) attrbufptr )++ = 0; } if ( a & ATTR_VOL_FILECOUNT ) { DebugLog ( ( "ATTR_VOL_FILECOUNT : %d\n", 0 ) ); *( ( UInt32 * ) attrbufptr )++ = cddaNodePtr->u.directory.entryCount - kNumberOfFakeDirEntries + 1; } if ( a & ATTR_VOL_DIRCOUNT ) { DebugLog ( ( "ATTR_VOL_DIRCOUNT : %d\n", 0 ) ); *( ( UInt32 * ) attrbufptr )++ = 1; } if ( a & ATTR_VOL_MAXOBJCOUNT ) { DebugLog ( ( "ATTR_VOL_MAXOBJCOUNT : %d\n", 0xFFFFFFFF ) ); *( ( UInt32 * ) attrbufptr )++ = 0xFFFFFFFF; } if ( a & ATTR_VOL_NAME ) { DebugLog ( ( "ATTR_VOL_NAME : %s\n", cddaNodePtr->u.directory.name ) ); attrlength = strlen ( cddaNodePtr->u.directory.name ) + 1; ( ( struct attrreference * ) attrbufptr )->attr_dataoffset = ( UInt8 * ) varbufptr - ( UInt8 * ) attrbufptr; ( ( struct attrreference * ) attrbufptr )->attr_length = attrlength; ( void ) strncpy ( ( UInt8 * ) varbufptr, cddaNodePtr->u.directory.name, attrlength ); // Advance beyond the space just allocated and round up to the next 4-byte boundary: ( UInt8 * ) varbufptr += attrlength + ( ( 4 - ( attrlength & 3 ) ) & 3 ); ++( ( struct attrreference * ) attrbufptr ); } if ( a & ATTR_VOL_MOUNTFLAGS ) { DebugLog ( ( "ATTR_VOL_MOUNTFLAGS : %d\n", cddaNodePtr->vNodePtr->v_mount->mnt_flag ) ); *( ( UInt32 * ) attrbufptr )++ = ( UInt32 ) cddaNodePtr->vNodePtr->v_mount->mnt_flag; } if ( a & ATTR_VOL_MOUNTEDDEVICE ) { DebugLog ( ( "ATTR_VOL_MOUNTFLAGS : %s\n", cddaNodePtr->vNodePtr->v_mount->mnt_stat.f_mntfromname ) ); ( ( struct attrreference * ) attrbufptr )->attr_dataoffset = ( UInt8 * ) varbufptr - ( UInt8 * ) attrbufptr; ( ( struct attrreference * ) attrbufptr )->attr_length = strlen ( cddaNodePtr->vNodePtr->v_mount->mnt_stat.f_mntfromname ) + 1; attrlength = ( ( struct attrreference * ) attrbufptr )->attr_length; // round up to the next 4-byte boundary: attrlength = attrlength + ( ( 4 - ( attrlength & 3 ) ) & 3 ); ( void ) bcopy ( cddaNodePtr->vNodePtr->v_mount->mnt_stat.f_mntfromname, varbufptr, attrlength ); // Advance beyond the space just allocated: ( UInt8 * ) varbufptr += attrlength; ++( ( struct attrreference * ) attrbufptr ); } if ( a & ATTR_VOL_ENCODINGSUSED ) { DebugLog ( ( "ATTR_VOL_ENCODINGSUSED : %d\n", 0 ) ); *( ( UInt64 * ) attrbufptr )++ = ( UInt64 ) 0; } if ( a & ATTR_VOL_CAPABILITIES ) { DebugLog ( ( "ATTR_VOL_CAPABILITIES\n" ) ); ( ( vol_capabilities_attr_t * ) attrbufptr )->capabilities[VOL_CAPABILITIES_FORMAT] = VOL_CAP_FMT_PERSISTENTOBJECTIDS; ( ( vol_capabilities_attr_t * ) attrbufptr )->capabilities[VOL_CAPABILITIES_INTERFACES] = VOL_CAP_INT_ATTRLIST; ( ( vol_capabilities_attr_t * ) attrbufptr )->capabilities[VOL_CAPABILITIES_RESERVED1] = 0; ( ( vol_capabilities_attr_t * ) attrbufptr )->capabilities[VOL_CAPABILITIES_RESERVED2] = 0; ( ( vol_capabilities_attr_t * ) attrbufptr )->valid[VOL_CAPABILITIES_FORMAT] = VOL_CAP_FMT_PERSISTENTOBJECTIDS; ( ( vol_capabilities_attr_t * ) attrbufptr )->valid[VOL_CAPABILITIES_INTERFACES] = VOL_CAP_INT_ATTRLIST; ( ( vol_capabilities_attr_t * ) attrbufptr )->valid[VOL_CAPABILITIES_RESERVED1] = 0; ( ( vol_capabilities_attr_t * ) attrbufptr )->valid[VOL_CAPABILITIES_RESERVED2] = 0; ++( ( vol_capabilities_attr_t * ) attrbufptr ); } if ( a & ATTR_VOL_ATTRIBUTES ) { DebugLog ( ( "ATTR_VOL_ATTRIBUTES\n" ) ); ( ( vol_attributes_attr_t * ) attrbufptr )->validattr.commonattr = ATTR_CMN_VALIDMASK; ( ( vol_attributes_attr_t * ) attrbufptr )->validattr.volattr = ATTR_VOL_VALIDMASK; ( ( vol_attributes_attr_t * ) attrbufptr )->validattr.dirattr = ATTR_DIR_VALIDMASK; ( ( vol_attributes_attr_t * ) attrbufptr )->validattr.fileattr = ATTR_FILE_VALIDMASK; ( ( vol_attributes_attr_t * ) attrbufptr )->validattr.forkattr = ATTR_FORK_VALIDMASK; ( ( vol_attributes_attr_t * ) attrbufptr )->nativeattr.commonattr = ATTR_CMN_VALIDMASK; ( ( vol_attributes_attr_t * ) attrbufptr )->nativeattr.volattr = ATTR_VOL_VALIDMASK; ( ( vol_attributes_attr_t * ) attrbufptr )->nativeattr.dirattr = ATTR_DIR_VALIDMASK; ( ( vol_attributes_attr_t * ) attrbufptr )->nativeattr.fileattr = ATTR_FILE_VALIDMASK; ( ( vol_attributes_attr_t * ) attrbufptr )->nativeattr.forkattr = ATTR_FORK_VALIDMASK; ++( ( vol_attributes_attr_t * ) attrbufptr ); } } *attrbufHandle = attrbufptr; *varbufHandle = varbufptr; DebugLog ( ( "PackVolumeAttributes exiting\n" ) ); } void PackCommonAttributes ( struct attrlist * attrListPtr, AppleCDDANodePtr cddaNodePtr, void ** attrbufHandle, void ** varbufHandle ) { void * attrbufptr; void * varbufptr; attrgroup_t a; UInt32 attrlength; DebugLog ( ( "PackCommonAttributes called\n" ) ); attrbufptr = *attrbufHandle; varbufptr = *varbufHandle; if ( ( a = attrListPtr->commonattr ) != 0 ) { if ( a & ATTR_CMN_NAME ) { // special case root since we know how to get it's name if ( cddaNodePtr->nodeType == kAppleCDDADirectoryType ) { DebugLog ( ( "ATTR_CMN_NAME : %s\n", cddaNodePtr->u.directory.name ) ); attrlength = strlen ( cddaNodePtr->u.directory.name ) + 1; ( void ) strncpy ( ( UInt8 * ) varbufptr, cddaNodePtr->u.directory.name, attrlength ); } // Special case the XMLFileNode else if ( cddaNodePtr->nodeType == kAppleCDDXMLFileType ) { DebugLog ( ( "ATTR_CMN_NAME : %s\n", ".TOC.plist" ) ); attrlength = strlen ( ".TOC.plist" ) + 1; ( void ) strncpy ( ( UInt8 * ) varbufptr, ".TOC.plist", attrlength ); } else { DebugLog ( ( "ATTR_CMN_NAME : %s\n", cddaNodePtr->u.file.nodeInfoPtr->name ) ); attrlength = cddaNodePtr->u.file.nodeInfoPtr->nameSize + 1; ( void ) strncpy ( ( UInt8 * ) varbufptr, cddaNodePtr->u.file.nodeInfoPtr->name, attrlength ); } ( ( struct attrreference * ) attrbufptr )->attr_dataoffset = ( UInt8 * ) varbufptr - ( UInt8 * ) attrbufptr; ( ( struct attrreference * ) attrbufptr )->attr_length = attrlength; // Advance beyond the space just allocated and round up to the next 4-byte boundary: ( UInt8 * ) varbufptr += attrlength + ( ( 4 - ( attrlength & 3 ) ) & 3 ); ++( ( struct attrreference * ) attrbufptr ); } if ( a & ATTR_CMN_DEVID ) { DebugLog ( ( "ATTR_CMN_DEVID : %ld\n", *( dev_t * ) &( CDDATOV ( cddaNodePtr )->v_mount->mnt_stat.f_fsid ) ) ); *( ( dev_t * ) attrbufptr )++ = *( dev_t * ) &( CDDATOV ( cddaNodePtr )->v_mount->mnt_stat.f_fsid ); //*( ( dev_t * ) attrbufptr )++ = cddaNodePtr->blockDeviceVNodePtr->v_specinfo->si_rdev; } if ( a & ATTR_CMN_FSID ) { DebugLog ( ( "ATTR_CMN_FSID\n" ) ); *( ( fsid_t * ) attrbufptr )++ = CDDATOV ( cddaNodePtr )->v_mount->mnt_stat.f_fsid; } if ( a & ATTR_CMN_OBJTYPE ) { DebugLog ( ( "ATTR_CMN_OBJTYPE\n" ) ); *( ( fsobj_type_t * ) attrbufptr )++ = CDDATOV ( cddaNodePtr )->v_type; } if ( a & ATTR_CMN_OBJTAG ) { DebugLog ( ( "ATTR_CMN_OBJTAG\n" ) ); *( ( fsobj_tag_t * ) attrbufptr )++ = CDDATOV ( cddaNodePtr )->v_tag; } if ( a & ATTR_CMN_OBJID ) { // special case root since we know how to get it's name if ( cddaNodePtr->nodeType == kAppleCDDADirectoryType ) { DebugLog ( ( "ATTR_CMN_OBJID: kAppleCDDARootFileID\n" ) ); // force root to be 2 ( ( fsobj_id_t * ) attrbufptr )->fid_objno = kAppleCDDARootFileID; } // Special case the XMLFileNode else if ( cddaNodePtr->nodeType == kAppleCDDXMLFileType ) { DebugLog ( ( "ATTR_CMN_OBJID: kAppleCDDAXMLFileID\n" ) ); // force the XMLFileNode to be 3 ( ( fsobj_id_t * ) attrbufptr )->fid_objno = kAppleCDDAXMLFileID; } else { DebugLog ( ( "ATTR_CMN_OBJID: nodeID = %ld\n", cddaNodePtr->nodeID ) ); ( ( fsobj_id_t * ) attrbufptr )->fid_objno = cddaNodePtr->nodeID; } ( ( fsobj_id_t * ) attrbufptr )->fid_generation = 0; ++( ( fsobj_id_t * ) attrbufptr ); } if ( a & ATTR_CMN_OBJPERMANENTID ) { // special case root if ( cddaNodePtr->nodeType == kAppleCDDADirectoryType ) { DebugLog ( ( "ATTR_CMN_OBJPERMANENTID: kAppleCDDARootFileID\n" ) ); // force root to be 2 ( ( fsobj_id_t * ) attrbufptr )->fid_objno = kAppleCDDARootFileID; } // Special case the XMLFileNode else if ( cddaNodePtr->nodeType == kAppleCDDXMLFileType ) { DebugLog ( ( "ATTR_CMN_OBJPERMANENTID: kAppleCDDAXMLFileID\n" ) ); // force the XMLFileNode to be 3 ( ( fsobj_id_t * ) attrbufptr )->fid_objno = kAppleCDDAXMLFileID; } else { DebugLog ( ( "ATTR_CMN_OBJPERMANENTID: nodeID = %ld\n", cddaNodePtr->nodeID ) ); ( ( fsobj_id_t * ) attrbufptr )->fid_objno = cddaNodePtr->nodeID; } ( ( fsobj_id_t * ) attrbufptr )->fid_generation = 0; ++( ( fsobj_id_t * ) attrbufptr ); } if ( a & ATTR_CMN_PAROBJID ) { // What node are they asking for? if ( cddaNodePtr->nodeID == kAppleCDDARootFileID ) { DebugLog ( ( "ATTR_CMN_PAROBJID: 1\n" ) ); // If this is the root directory and they want the parent, force it to 1 ( ( fsobj_id_t * ) attrbufptr )->fid_objno = 1; } else { DebugLog ( ( "ATTR_CMN_PAROBJID: kAppleCDDARootFileID\n" ) ); // Every other object has the root as its parent (flat filesystem) ( ( fsobj_id_t * ) attrbufptr )->fid_objno = kAppleCDDARootFileID; } ( ( fsobj_id_t * ) attrbufptr )->fid_generation = 0; ++( ( fsobj_id_t * ) attrbufptr ); } if ( a & ATTR_CMN_SCRIPT ) { DebugLog ( ( "ATTR_CMN_SCRIPT\n" ) ); *( ( text_encoding_t * ) attrbufptr )++ = 0; } if ( a & ATTR_CMN_CRTIME ) { DebugLog ( ( "ATTR_CMN_CRTIME\n" ) ); *( ( struct timespec * ) attrbufptr )++ = VFSTOCDDA ( cddaNodePtr->vNodePtr->v_mount )->mountTime; } if ( a & ATTR_CMN_MODTIME ) { DebugLog ( ( "ATTR_CMN_MODTIME\n" ) ); *( ( struct timespec * ) attrbufptr )++ = VFSTOCDDA ( cddaNodePtr->vNodePtr->v_mount )->mountTime; } if ( a & ATTR_CMN_CHGTIME ) { DebugLog ( ( "ATTR_CMN_CHGTIME\n" ) ); *( ( struct timespec * ) attrbufptr )++ = cddaNodePtr->lastModTime; } if ( a & ATTR_CMN_ACCTIME ) { DebugLog ( ( "ATTR_CMN_ACCTIME\n" ) ); *( ( struct timespec * ) attrbufptr )++ = cddaNodePtr->accessTime; } if ( a & ATTR_CMN_BKUPTIME ) { DebugLog ( ( "ATTR_CMN_BKUPTIME\n" ) ); ( ( struct timespec * ) attrbufptr )->tv_sec = 0; ( ( struct timespec * ) attrbufptr )->tv_nsec = 0; ++( ( struct timespec * ) attrbufptr ); } if ( a & ATTR_CMN_FNDRINFO ) { FinderInfo finderInfo = { 0 }; DebugLog ( ( "ATTR_CMN_FNDRINFO\n" ) ); if ( cddaNodePtr->nodeID == kAppleCDDAXMLFileID ) { DebugLog ( ( "kFinderInfoInvisibleMask\n" ) ); // Make the XML file invisible finderInfo.finderFlags = kFinderInfoInvisibleMask; } else { finderInfo.finderFlags = kFinderInfoNoFileExtensionMask; } finderInfo.location.v = -1; finderInfo.location.h = -1; if ( ( CDDATOV ( cddaNodePtr )->v_type == VREG ) && ( cddaNodePtr->nodeID != kAppleCDDAXMLFileID ) ) { DebugLog ( ( "fileType, creator\n" ) ); finderInfo.fileType = VFSTOCDDA ( cddaNodePtr->vNodePtr->v_mount )->fileType; finderInfo.fileCreator = VFSTOCDDA ( cddaNodePtr->vNodePtr->v_mount )->fileCreator; } bcopy ( &finderInfo, attrbufptr, sizeof ( finderInfo ) ); ( UInt8 * ) attrbufptr += sizeof ( finderInfo ); bzero ( attrbufptr, kExtendedFinderInfoSize ); ( UInt8 * ) attrbufptr += kExtendedFinderInfoSize; } if ( a & ATTR_CMN_OWNERID ) { DebugLog ( ( "ATTR_CMN_OWNERID\n" ) ); *( ( uid_t * ) attrbufptr )++ = kUnknownUserID; } if ( a & ATTR_CMN_GRPID ) { DebugLog ( ( "ATTR_CMN_GRPID\n" ) ); *( ( gid_t * ) attrbufptr )++ = kUnknownGroupID; } if ( a & ATTR_CMN_ACCESSMASK ) { UInt32 access = S_IRUSR | S_IRGRP | S_IROTH; if ( cddaNodePtr->vNodePtr->v_flag & VROOT ) access |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; DebugLog ( ( "ATTR_CMN_ACCESSMASK\n" ) ); *( ( UInt32 * ) attrbufptr )++ = access; } if ( a & ATTR_CMN_FLAGS ) { DebugLog ( ( "ATTR_CMN_FLAGS\n" ) ); *( ( UInt32 * ) attrbufptr )++ = 0; // ??? } if ( a & ATTR_CMN_USERACCESS ) { UInt32 permissions = R_OK; DebugLog ( ( "ATTR_CMN_USERACCESS\n" ) ); if ( cddaNodePtr->vNodePtr->v_flag & VROOT ) permissions |= X_OK; *( ( UInt32 * ) attrbufptr )++ = permissions; } } *attrbufHandle = attrbufptr; *varbufHandle = varbufptr; DebugLog ( ( "PackCommonAttributes exiting\n" ) ); } void PackDirectoryAttributes ( struct attrlist * attrListPtr, AppleCDDANodePtr cddaNodePtr, void ** attrbufHandle, void ** varbufHandle ) { void * attrbufptr; attrgroup_t a; DebugLog ( ( "PackDirectoryAttributes called\n" ) ); attrbufptr = *attrbufHandle; a = attrListPtr->dirattr; if ( ( cddaNodePtr->vNodePtr->v_type == VDIR ) && ( a != 0 ) ) { if ( a & ATTR_DIR_LINKCOUNT ) { DebugLog ( ( "ATTR_DIR_LINKCOUNT\n" ) ); *( ( UInt32 * ) attrbufptr )++ = 0; // ??? } if ( a & ATTR_DIR_ENTRYCOUNT ) { DebugLog ( ( "ATTR_DIR_ENTRYCOUNT: %ld\n", cddaNodePtr->u.directory.entryCount - 2 ) ); // exclude '.' and '..' from total count *( ( UInt32 * ) attrbufptr )++ = cddaNodePtr->u.directory.entryCount - 2; } if ( a & ATTR_DIR_MOUNTSTATUS ) { DebugLog ( ( "ATTR_DIR_MOUNTSTATUS: %d\n", CDDATOV ( cddaNodePtr )->v_mountedhere ) ); if ( CDDATOV ( cddaNodePtr )->v_mountedhere ) { *( ( UInt32 * ) attrbufptr )++ = DIR_MNTSTATUS_MNTPOINT; } else { *( ( UInt32 * ) attrbufptr )++ = 0; } } } *attrbufHandle = attrbufptr; DebugLog ( ( "PackDirectoryAttributes exiting\n" ) ); } void PackFileAttributes ( struct attrlist * attrListPtr, AppleCDDANodePtr cddaNodePtr, void ** attrbufHandle, void ** varbufHandle ) { void * attrbufptr = *attrbufHandle; void * varbufptr = *varbufHandle; attrgroup_t a = attrListPtr->fileattr; DebugLog ( ( "PackFileAttributes called\n" ) ); if ( ( CDDATOV ( cddaNodePtr )->v_type == VREG ) && ( a != 0 ) ) { if ( a & ATTR_FILE_LINKCOUNT ) { DebugLog ( ( "ATTR_FILE_LINKCOUNT\n" ) ); *( ( UInt32 * ) attrbufptr )++ = 0; // ??? } if ( a & ATTR_FILE_TOTALSIZE ) { DebugLog ( ( "ATTR_FILE_TOTALSIZE\n" ) ); if ( cddaNodePtr->nodeID == kAppleCDDAXMLFileID ) *( ( off_t * ) attrbufptr )++ = ( off_t ) cddaNodePtr->u.xmlFile.fileSize; else *( ( off_t * ) attrbufptr )++ = ( off_t ) cddaNodePtr->u.file.nodeInfoPtr->numBytes; } if ( a & ATTR_FILE_ALLOCSIZE ) { DebugLog ( ( "ATTR_FILE_ALLOCSIZE\n" ) ); if ( cddaNodePtr->nodeID == kAppleCDDAXMLFileID ) *( ( off_t * ) attrbufptr )++ = ( off_t ) cddaNodePtr->u.xmlFile.fileSize; else *( ( off_t * ) attrbufptr )++ = ( off_t ) cddaNodePtr->u.file.nodeInfoPtr->numBytes; } if ( a & ATTR_FILE_IOBLOCKSIZE ) { DebugLog ( ( "ATTR_FILE_IOBLOCKSIZE\n" ) ); *( ( UInt32 * ) attrbufptr )++ = kAppleCDDABlockSize; } if ( a & ATTR_FILE_CLUMPSIZE ) { DebugLog ( ( "ATTR_FILE_CLUMPSIZE\n" ) ); *( ( UInt32 * ) attrbufptr )++ = kAppleCDDABlockSize; } if ( a & ATTR_FILE_DEVTYPE ) { DebugLog ( ( "ATTR_FILE_DEVTYPE\n" ) ); *( ( UInt32 * ) attrbufptr )++ = ( UInt32 ) 0; // ??? } if ( a & ATTR_FILE_DATALENGTH ) { DebugLog ( ( "ATTR_FILE_DATALENGTH\n" ) ); if ( cddaNodePtr->nodeID == kAppleCDDAXMLFileID ) *( ( off_t * ) attrbufptr )++ = ( off_t ) cddaNodePtr->u.xmlFile.fileSize; else *( ( off_t * ) attrbufptr )++ = ( off_t ) cddaNodePtr->u.file.nodeInfoPtr->numBytes; } if ( a & ATTR_FILE_DATAALLOCSIZE ) { DebugLog ( ( "ATTR_FILE_DATAALLOCSIZE\n" ) ); if ( cddaNodePtr->nodeID == kAppleCDDAXMLFileID ) *( ( off_t * ) attrbufptr )++ = ( off_t ) cddaNodePtr->u.xmlFile.fileSize; else *( ( off_t * ) attrbufptr )++ = ( off_t ) cddaNodePtr->u.file.nodeInfoPtr->numBytes; } if ( a & ATTR_FILE_RSRCLENGTH ) { DebugLog ( ( "ATTR_FILE_RSRCLENGTH\n" ) ); *( ( off_t * ) attrbufptr )++ = ( off_t ) 0; } if ( a & ATTR_FILE_RSRCALLOCSIZE ) { DebugLog ( ( "ATTR_FILE_RSRCALLOCSIZE\n" ) ); *( ( off_t * ) attrbufptr )++ = ( off_t ) 0; DebugLog ( ( "ATTR_FILE_RSRCALLOCSIZE done\n" ) ); } } *attrbufHandle = attrbufptr; *varbufHandle = varbufptr; DebugLog ( ( "PackFileAttributes exiting\n" ) ); } void PackAttributesBlock ( struct attrlist * attrListPtr, struct vnode * vNodePtr, void ** attrbufHandle, void ** varbufHandle ) { AppleCDDANodePtr cddaNodePtr = VTOCDDA ( vNodePtr ); DebugLog ( ( "PackAttributesBlock called\n" ) ); if ( attrListPtr->volattr != 0 ) { DebugLog ( ( "PackAttributesBlock: volume attributes requested.\n" ) ); PackVolumeAttributes ( attrListPtr, cddaNodePtr, attrbufHandle, varbufHandle ); } else { DebugLog ( ( "PackAttributesBlock: NO volume attributes requested.\n" ) ); PackCommonAttributes ( attrListPtr, cddaNodePtr, attrbufHandle, varbufHandle ); switch ( vNodePtr->v_type ) { case VDIR: DebugLog ( ( "PackAttributesBlock: directory attributes requested.\n" ) ); PackDirectoryAttributes ( attrListPtr, cddaNodePtr, attrbufHandle, varbufHandle ); break; case VREG: DebugLog ( ( "PackAttributesBlock: file attributes requested.\n" ) ); PackFileAttributes ( attrListPtr, cddaNodePtr, attrbufHandle, varbufHandle ); break; default: break; } } DebugLog ( ( "PackAttributesBlock exiting\n" ) ); } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // End Of File //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ