AppleCDDAFileSystemVNodeOps.c [plain text]
#ifndef __APPLE_CDDA_FS_VNODE_OPS_H__
#include "AppleCDDAFileSystemVNodeOps.h"
#endif
#ifndef __APPLE_CDDA_FS_DEBUG_H__
#include "AppleCDDAFileSystemDebug.h"
#endif
#ifndef __APPLE_CDDA_FS_DEFINES_H__
#include "AppleCDDAFileSystemDefines.h"
#endif
#ifndef __APPLE_CDDA_FS_UTILS_H__
#include "AppleCDDAFileSystemUtils.h"
#endif
#ifndef __APPLE_CDDA_FS_VFS_OPS_H__
#include "AppleCDDAFileSystemVFSOps.h"
#endif
#include <vm/vm_pageout.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/proc.h>
#include <sys/filedesc.h>
#include <sys/lock.h>
#include <sys/vnode.h>
#include <sys/dirent.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/malloc.h>
#include <sys/namei.h>
#include <sys/mbuf.h>
#include <sys/paths.h>
#include <sys/un.h>
#include <sys/unpcb.h>
#include <sys/errno.h>
#include <sys/ubc.h>
#include <vfs/vfs_support.h>
#include <miscfs/specfs/specdev.h>
extern int strcmp __P ( ( const char *, const char * ) ); extern int strncmp __P ( ( const char *, const char *, size_t length ) ); extern char * strcpy __P ( ( char *, const char * ) ); extern char * strncpy __P ( ( char *, const char *, size_t length ) ); extern char * strchr __P ( ( const char *, int ) ); extern int atoi __P ( ( const char * ) );
#define RENAME_SUPPORTED 0
static SInt32
AddDirectoryEntry ( UInt32 nodeID, UInt8 type, const char * name, struct uio * uio );
static SInt32
AddDirectoryEntry ( UInt32 nodeID,
UInt8 type,
const char * name,
struct uio * uio )
{
struct dirent directoryEntry;
SInt32 nameLength = 0;
UInt16 directoryEntryLength = 0;
DebugAssert ( ( name != NULL ) );
DebugAssert ( ( uio != NULL ) );
DebugLog ( ( "fileName = %s\n", name ) );
nameLength = strlen ( name );
DebugAssert ( ( nameLength < MAXNAMLEN + 1 ) );
directoryEntry.d_fileno = nodeID;
directoryEntry.d_reclen = sizeof ( directoryEntry );
directoryEntry.d_type = type;
directoryEntry.d_namlen = nameLength;
directoryEntryLength = directoryEntry.d_reclen;
strncpy ( directoryEntry.d_name, name, MAXNAMLEN );
bzero ( &directoryEntry.d_name[nameLength], MAXNAMLEN + 1 - nameLength );
if ( uio->uio_resid < directoryEntry.d_reclen )
{
directoryEntryLength = 0;
}
else
{
uiomove ( ( caddr_t ) &directoryEntry, sizeof ( directoryEntry ), uio );
}
return directoryEntryLength;
}
int
CDDA_Lookup ( struct vop_lookup_args * lookupArgsPtr )
{
struct componentname * compNamePtr = NULL;
struct vnode ** vNodeHandle = NULL;
struct vnode * parentVNodePtr = NULL;
struct vnode * vNodePtr = NULL;
struct proc * theProcPtr = NULL;
AppleCDDANodePtr parentCDDANodePtr = NULL;
AppleCDDAMountPtr cddaMountPtr = NULL;
AppleCDDANodeInfoPtr nodeInfoArrayPtr = NULL;
UInt32 index = 0;
int error = 0;
int flags = 0;
int lockParent = 0;
DebugLog ( ( "CDDA_Lookup: Entering.\n" ) );
DebugAssert ( ( lookupArgsPtr != NULL ) );
compNamePtr = lookupArgsPtr->a_cnp;
vNodeHandle = lookupArgsPtr->a_vpp;
parentVNodePtr = lookupArgsPtr->a_dvp;
DebugAssert ( ( compNamePtr != NULL ) );
DebugAssert ( ( vNodeHandle != NULL ) );
DebugAssert ( ( parentVNodePtr != NULL ) );
theProcPtr = compNamePtr->cn_proc;
parentCDDANodePtr = VTOCDDA ( parentVNodePtr );
cddaMountPtr = VFSTOCDDA ( parentVNodePtr->v_mount );
DebugAssert ( ( theProcPtr != NULL ) );
DebugAssert ( ( parentCDDANodePtr != NULL ) );
DebugAssert ( ( cddaMountPtr != NULL ) );
*vNodeHandle = NULL;
flags = compNamePtr->cn_flags;
lockParent = flags & LOCKPARENT;
#if RENAME_SUPPORTED
if ( compNamePtr->cn_nameiop == CREATE )
{
DebugLog ( ( "Can't CREATE %s, returning EROFS\n", compNamePtr->cn_nameptr ) );
error = EROFS;
goto Exit;
}
if ( compNamePtr->cn_nameiop == RENAME )
{
DebugLog ( ( "Can't RENAME %s, returning EJUSTRETURN\n", compNamePtr->cn_nameptr ) );
error = EJUSTRETURN;
goto Exit;
}
if ( compNamePtr->cn_nameiop == DELETE )
{
DebugLog ( ( "Can't DELETE %s\n", compNamePtr->cn_nameptr ) );
}
#else
if ( compNamePtr->cn_nameiop == CREATE ||
compNamePtr->cn_nameiop == RENAME ||
compNamePtr->cn_nameiop == DELETE )
{
DebugLog ( ( "Can't CREATE %s, returning EROFS\n", compNamePtr->cn_nameptr ) );
error = EROFS;
goto Exit;
}
#endif
if ( ( flags & ISLASTCN ) == 0 && bcmp ( &compNamePtr->cn_nameptr[compNamePtr->cn_namelen],
_PATH_RSRCFORKSPEC,
sizeof ( _PATH_RSRCFORKSPEC ) - 1 ) == 0 )
{
DebugLog ( ( "No resource forks available, return ENOTDIR.\n" ) );
compNamePtr->cn_consume = sizeof ( _PATH_RSRCFORKSPEC ) - 1;
error = ENOTDIR;
goto Exit;
}
if ( parentVNodePtr->v_type != VDIR )
{
DebugLog ( ( "parentVNodePtr->v_type != VDIR, returning ENOTDIR\n" ) );
error = ENOTDIR;
goto Exit;
}
DebugLog ( ( "Looking for name = %s.\n", compNamePtr->cn_nameptr ) );
if ( compNamePtr->cn_nameptr[0] == '.' )
{
if ( compNamePtr->cn_namelen == 1 )
{
DebugLog ( ( ". was requested\n" ) );
vNodePtr = parentVNodePtr;
VREF ( vNodePtr );
error = 0;
*vNodeHandle = vNodePtr;
goto Exit;
}
else if ( ( compNamePtr->cn_namelen == 2 ) && ( compNamePtr->cn_nameptr[1] == '.' ) )
{
panic ( "CDDA_Lookup: namei asked for .. when it shouldn't have" );
}
else if ( ( compNamePtr->cn_namelen == 10 ) && ( !strncmp ( &compNamePtr->cn_nameptr[1], "TOC.plist", 9 ) ) )
{
DebugLog ( ( ".TOC.plist was requested\n" ) );
error = vget ( cddaMountPtr->xmlFileVNodePtr, LK_EXCLUSIVE, theProcPtr );
if ( error != 0 )
{
DebugLog ( ( "CDDA_Lookup: exiting with error = %d after vget.\n", error ) );
goto Exit;
}
if ( !lockParent || !( flags & ISLASTCN ) )
{
VOP_UNLOCK ( parentVNodePtr, 0, theProcPtr );
}
if ( ! ( flags & LOCKLEAF ) )
{
VOP_UNLOCK ( cddaMountPtr->xmlFileVNodePtr, 0, theProcPtr );
}
*vNodeHandle = cddaMountPtr->xmlFileVNodePtr;
goto Exit;
}
}
if ( strcmp ( &compNamePtr->cn_nameptr[0], parentCDDANodePtr->u.directory.name ) == 0 )
{
DebugLog ( ( "The root directory was requested by name = %s\n", parentCDDANodePtr->u.directory.name ) );
vNodePtr = parentVNodePtr;
VREF ( vNodePtr );
error = 0;
*vNodeHandle = vNodePtr;
goto Exit;
}
nodeInfoArrayPtr = VFSTONODEINFO ( parentVNodePtr->v_mount );
DebugAssert ( ( nodeInfoArrayPtr != NULL ) );
LOOP:
DebugLog ( ( "Locking nodeInfoLock.\n" ) );
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_EXCLUSIVE, NULL, theProcPtr );
index = 0;
while ( index < ( parentCDDANodePtr->u.directory.entryCount - kNumberOfFakeDirEntries ) )
{
if ( nodeInfoArrayPtr->nameSize == compNamePtr->cn_namelen &&
!strcmp ( nodeInfoArrayPtr->name, compNamePtr->cn_nameptr ) )
{
if ( nodeInfoArrayPtr->vNodePtr != NULL )
{
vNodePtr = nodeInfoArrayPtr->vNodePtr;
DebugLog ( ( "Releasing nodeInfoLock.\n" ) );
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_RELEASE, NULL, theProcPtr );
error = vget ( vNodePtr, LK_EXCLUSIVE, theProcPtr );
if ( error != 0 )
{
DebugLog ( ( "CDDA_Lookup: exiting with error = %d after vget.\n", error ) );
goto LOOP;
}
if ( !lockParent || !( flags & ISLASTCN ) )
{
VOP_UNLOCK ( parentVNodePtr, 0, theProcPtr );
}
if ( ! ( flags & LOCKLEAF ) )
{
VOP_UNLOCK ( vNodePtr, 0, theProcPtr );
}
*vNodeHandle = vNodePtr;
goto Exit;
}
else
{
int error2 = 0;
DebugLog ( ( "Couldn't find the vnode...Calling CreateNewCDDAFile\n" ) );
DebugLog ( ( "Releasing nodeInfoLock.\n" ) );
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_RELEASE, NULL, theProcPtr );
error2 = CreateNewCDDAFile ( parentVNodePtr->v_mount,
nodeInfoArrayPtr->trackDescriptor.point + kOffsetForFiles,
nodeInfoArrayPtr,
theProcPtr,
&vNodePtr );
DebugLog ( ( "Locking nodeInfoLock.\n" ) );
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_EXCLUSIVE, NULL, theProcPtr );
nodeInfoArrayPtr->vNodePtr = vNodePtr;
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_RELEASE, NULL, theProcPtr );
if ( error != 0 || error2 != 0 )
goto Exit;
if ( !lockParent || !( flags & ISLASTCN ) )
{
VOP_UNLOCK ( parentVNodePtr, 0, theProcPtr );
}
if ( ! ( flags & LOCKLEAF ) )
{
VOP_UNLOCK ( vNodePtr, 0, theProcPtr );
}
*vNodeHandle = vNodePtr;
goto Exit;
}
}
index++;
nodeInfoArrayPtr++;
}
DebugLog ( ( "Releasing nodeInfoLock...About to return ENOENT.\n" ) );
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_RELEASE, NULL, theProcPtr );
return ( ENOENT );
Exit:
DebugLog ( ( "CDDA_Lookup: exiting from Exit with error = %d.\n", error ) );
return ( error );
}
int
CDDA_Open ( struct vop_open_args * openArgsPtr )
{
struct vnode * vNodePtr = NULL;
int error = 0;
DebugLog ( ( "CDDA_Open: Entering.\n" ) );
DebugAssert ( ( openArgsPtr != NULL ) );
vNodePtr = openArgsPtr->a_vp;
DebugAssert ( ( vNodePtr != NULL ) );
if ( vNodePtr->v_type != VREG && vNodePtr->v_type != VDIR )
{
DebugLog ( ( "Error = %d, wrong v_type.\n", ENOTSUP ) );
error = ENOTSUP;
goto ERROR;
}
vNodePtr->v_flag |= VRAOFF;
ERROR:
DebugLog ( ( "CDDA_Open: exiting with error = %d.\n", error ) );
return ( error );
}
int
CDDA_Close ( struct vop_close_args * closeArgsPtr )
{
DebugLog ( ( "CDDA_Close: Entering.\n" ) );
#if DEBUG
DebugAssert ( ( closeArgsPtr != NULL ) );
#else
#pragma unused ( closeArgsPtr )
#endif
DebugLog ( ( "CDDA_Close: exiting...\n" ) );
return ( 0 );
}
int
CDDA_Read ( struct vop_read_args * readArgsPtr )
{
register struct vnode * vNodePtr = NULL;
register struct uio * uio = NULL;
AppleCDDANodePtr cddaNodePtr = NULL;
int error = 0;
DebugLog ( ( "CDDA_Read: Entering.\n" ) );
DebugAssert ( ( readArgsPtr ) );
vNodePtr = readArgsPtr->a_vp;
uio = readArgsPtr->a_uio;
DebugAssert ( ( vNodePtr != NULL ) );
DebugAssert ( ( uio != NULL ) );
DebugAssert ( ( UBCINFOEXISTS ( vNodePtr ) != 0 ) );
cddaNodePtr = VTOCDDA ( vNodePtr );
DebugAssert ( ( cddaNodePtr != NULL ) );
cddaNodePtr->flags |= kAppleCDDAAccessedMask;
if ( vNodePtr->v_type != VREG )
{
DebugLog ( ( "CDDA_Read: not a file, exiting with error = %d.\n", EISDIR ) );
return ( EISDIR );
}
if ( uio->uio_resid == 0 )
{
DebugLog ( ( "CDDA_Read: uio_resid = 0, no data requested" ) );
return ( 0 );
}
if ( uio->uio_offset < 0 )
{
DebugLog ( ( "CDDA_Read: Can't read from a negative offset..." ) );
return ( EINVAL );
}
if ( cddaNodePtr->nodeType == kAppleCDDAXMLFileType )
{
off_t offset = uio->uio_offset;
UInt32 amountToCopy = 0;
UInt32 numBytes = 0;
numBytes = cddaNodePtr->u.xmlFile.fileSize;
if ( uio->uio_offset > numBytes )
{
DebugLog ( ( "CDDA_Read: Can't read past end of file..." ) );
return ( 0 );
}
amountToCopy = ulmin ( uio->uio_resid, numBytes - offset );
uiomove ( ( caddr_t ) &cddaNodePtr->u.xmlFile.fileDataPtr[offset],
amountToCopy,
uio );
return ( 0 );
}
else if ( cddaNodePtr->nodeType == kAppleCDDATrackType )
{
UInt32 headerSize = 0;
UInt32 count = 0;
UInt32 blockNumber = 0;
off_t offset = 0;
off_t sectorOffset = 0;
struct buf * bufPtr = NULL;
offset = uio->uio_offset;
if ( offset > cddaNodePtr->u.file.nodeInfoPtr->numBytes )
{
DebugLog ( ( "CDDA_Read: Can't read past end of file..." ) );
return ( 0 );
}
headerSize = sizeof ( cddaNodePtr->u.file.aiffHeader );
if ( offset < headerSize )
{
UInt32 amountToCopy = 0;
amountToCopy = ulmin ( uio->uio_resid, headerSize - offset );
uiomove ( ( caddr_t ) &cddaNodePtr->u.file.aiffHeader.u.alignedHeader.filler[offset],
amountToCopy,
uio );
offset += amountToCopy;
}
if ( ( uio->uio_resid > 0 ) &&
( uio->uio_offset < cddaNodePtr->u.file.nodeInfoPtr->numBytes ) )
{
offset -= headerSize;
sectorOffset = offset % kPhysicalMediaBlockSize;
blockNumber = ( offset / kPhysicalMediaBlockSize ) + cddaNodePtr->u.file.nodeInfoPtr->LBA;
if ( sectorOffset != 0 )
{
count = ulmin ( uio->uio_resid, ( kPhysicalMediaBlockSize - sectorOffset ) );
count = ulmin ( count, cddaNodePtr->u.file.nodeInfoPtr->numBytes - uio->uio_offset );
error = bread ( cddaNodePtr->blockDeviceVNodePtr,
blockNumber,
kPhysicalMediaBlockSize,
NOCRED,
&bufPtr );
if ( error != 0 )
{
brelse ( bufPtr );
return ( error );
}
uiomove ( bufPtr->b_data + sectorOffset, count, uio );
SET ( bufPtr->b_flags, B_INVAL );
brelse ( bufPtr );
blockNumber++;
}
while ( ( uio->uio_resid > kPhysicalMediaBlockSize ) &&
( uio->uio_offset < cddaNodePtr->u.file.nodeInfoPtr->numBytes ) )
{
UInt32 blocksToRead = 0;
if ( uio->uio_resid > kMaxBytesPerRead )
{
blocksToRead = kMaxBlocksPerRead;
count = kMaxBytesPerRead;
}
else
{
blocksToRead = uio->uio_resid / kPhysicalMediaBlockSize;
count = blocksToRead * kPhysicalMediaBlockSize;
}
error = bread ( cddaNodePtr->blockDeviceVNodePtr,
blockNumber,
count,
NOCRED,
&bufPtr );
if ( error != 0 )
{
brelse ( bufPtr );
return ( error );
}
count = ulmin ( count, cddaNodePtr->u.file.nodeInfoPtr->numBytes - uio->uio_offset );
uiomove ( bufPtr->b_data, count, uio );
SET ( bufPtr->b_flags, B_INVAL );
brelse ( bufPtr );
blockNumber += blocksToRead;
}
if ( ( uio->uio_resid > 0 ) &&
( uio->uio_offset < cddaNodePtr->u.file.nodeInfoPtr->numBytes ) )
{
count = ulmin ( uio->uio_resid, cddaNodePtr->u.file.nodeInfoPtr->numBytes - uio->uio_offset );
error = bread ( cddaNodePtr->blockDeviceVNodePtr,
blockNumber,
kPhysicalMediaBlockSize,
NOCRED,
&bufPtr );
if ( error != 0 )
{
brelse ( bufPtr );
return ( error );
}
uiomove ( bufPtr->b_data, count, uio );
brelse ( bufPtr );
}
}
}
DebugLog ( ( "CDDA_Read: exiting.\n" ) );
return ( error );
}
int
CDDA_ReadDir ( struct vop_readdir_args * readDirArgsPtr )
{
struct vnode * vNodePtr = NULL;
AppleCDDANodePtr cddaNodePtr = NULL;
AppleCDDAMountPtr cddaMountPtr = NULL;
AppleCDDANodeInfoPtr nodeInfoArrayPtr = NULL;
struct proc * theProcPtr = NULL;
struct uio * uio = NULL;
UInt32 index = 0;
int error = 0;
SInt32 offsetValue = 0;
UInt32 direntSize = 0;
DebugLog ( ( "CDDA_ReadDir: Entering.\n" ) );
DebugAssert ( ( readDirArgsPtr != NULL ) );
vNodePtr = readDirArgsPtr->a_vp;
uio = readDirArgsPtr->a_uio;
DebugAssert ( ( vNodePtr != NULL ) );
DebugAssert ( ( uio != NULL ) );
theProcPtr = current_proc ( );
cddaNodePtr = VTOCDDA ( vNodePtr );
DebugAssert ( ( theProcPtr != NULL ) );
DebugAssert ( ( cddaNodePtr != NULL ) );
if ( readDirArgsPtr->a_ncookies != NULL || readDirArgsPtr->a_cookies != NULL )
{
DebugLog ( ( "No cookie exporting, exiting with error = %d.\n", EINVAL ) );
return EINVAL;
}
if ( vNodePtr->v_type != VDIR )
{
DebugLog ( ( "CDDA_ReadDir: not a directory, exiting with error = %d.\n", ENOTDIR ) );
return ( ENOTDIR );
}
if ( cddaNodePtr->nodeID != kAppleCDDARootFileID )
{
DebugLog ( ( "CDDA_ReadDir: not root directory, exiting with error = %d.\n", EINVAL ) );
return ( EINVAL );
}
if ( uio->uio_iovcnt > 1 )
{
DebugLog ( ( "More than one buffer, exiting with error = %d.\n", EINVAL ) );
return ( EINVAL );
}
if ( uio->uio_resid < sizeof ( struct dirent ) )
{
DebugLog ( ( "resid < dirent size, exiting with error = %d.\n", EINVAL ) );
return ( EINVAL );
}
direntSize = sizeof ( struct dirent );
if ( uio->uio_offset == 0 )
{
offsetValue = AddDirectoryEntry ( cddaNodePtr->nodeID, DT_DIR, ".", uio );
if ( offsetValue == 0 )
{
DebugLog ( ( "offsetValue is zero, exiting with error = %d.\n", 0 ) );
return 0;
}
}
if ( uio->uio_offset == direntSize )
{
offsetValue = AddDirectoryEntry ( cddaNodePtr->nodeID, DT_DIR, "..", uio );
if ( offsetValue == 0 )
{
DebugLog ( ( "offsetValue is zero, exiting with error = %d.\n", 0 ) );
return 0;
}
}
if ( uio->uio_offset == direntSize * kAppleCDDARootFileID )
{
offsetValue += AddDirectoryEntry ( kAppleCDDAXMLFileID, kAppleCDDAXMLFileType, ".TOC.plist", uio );
if ( offsetValue == 0 )
{
DebugLog ( ( "offsetValue is zero, exiting with error = %d.\n", 0 ) );
return 0;
}
}
nodeInfoArrayPtr = VFSTONODEINFO ( vNodePtr->v_mount );
cddaMountPtr = VFSTOCDDA ( vNodePtr->v_mount );
DebugAssert ( ( nodeInfoArrayPtr != NULL ) );
DebugAssert ( ( cddaMountPtr != NULL ) );
DebugLog ( ( "cddaMountPtr->numTracks = %ld.\n", cddaMountPtr->numTracks ) );
DebugLog ( ( "buffer size needed = %ld.\n", direntSize * ( cddaMountPtr->numTracks + kNumberOfFakeDirEntries ) ) );
for ( index = 0; index < cddaMountPtr->numTracks; index++, nodeInfoArrayPtr++ )
{
DebugLog ( ( "uio->uio_offset = %ld.\n", uio->uio_offset ) );
DebugLog ( ( "uio->uio_resid = %ld.\n", uio->uio_resid ) );
if ( uio->uio_offset == direntSize * ( index + kNumberOfFakeDirEntries ) )
{
DebugLog ( ( "index = %ld.\n", index ) );
offsetValue = AddDirectoryEntry ( nodeInfoArrayPtr->trackDescriptor.point,
kAppleCDDATrackType,
nodeInfoArrayPtr->name,
uio );
if ( offsetValue == 0 )
{
DebugLog ( ( "offsetValue is zero, exiting with error = %d.\n", 0 ) );
return 0;
}
}
}
if ( readDirArgsPtr->a_eofflag )
{
DebugLog ( ( "eofflag = %d.\n", ( uio->uio_offset >= direntSize * ( cddaMountPtr->numTracks + kNumberOfFakeDirEntries ) ) ? 1 : 0 ) );
*readDirArgsPtr->a_eofflag = ( uio->uio_offset >= direntSize * ( cddaMountPtr->numTracks + kNumberOfFakeDirEntries ) ) ? 1 : 0;
error = 0;
}
DebugLog ( ( "CDDA_ReadDir: exiting with error = %d.\n", error ) );
return ( error );
}
int
CDDA_PageIn ( struct vop_pagein_args * pageInArgsPtr )
{
register struct vnode * vNodePtr = NULL;
AppleCDDANodePtr cddaNodePtr = NULL;
int error = 0;
int nocommit = 0;
UInt32 numBytes = 0;
DebugLog ( ( "CDDA_PageIn: Entering.\n" ) );
DebugAssert ( ( pageInArgsPtr != NULL ) );
vNodePtr = pageInArgsPtr->a_vp;
nocommit = pageInArgsPtr->a_flags & UPL_NOCOMMIT;
DebugAssert ( ( vNodePtr != NULL ) );
cddaNodePtr = VTOCDDA ( vNodePtr );
DebugAssert ( ( cddaNodePtr != NULL ) );
if ( vNodePtr->v_type != VREG )
panic ( "CDDA_PageIn: vNodePtr not UBC type.\n" );
if ( cddaNodePtr->nodeType == kAppleCDDAXMLFileType )
{
numBytes = cddaNodePtr->u.xmlFile.fileSize;
}
else if ( cddaNodePtr->nodeType == kAppleCDDATrackType )
{
numBytes = cddaNodePtr->u.file.nodeInfoPtr->numBytes;
}
if ( pageInArgsPtr->a_size == 0 )
{
if ( !nocommit )
{
ubc_upl_abort_range ( pageInArgsPtr->a_pl,
pageInArgsPtr->a_pl_offset,
pageInArgsPtr->a_size,
UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY );
}
return ( error );
}
if ( pageInArgsPtr->a_f_offset < 0 )
{
if ( !nocommit )
{
ubc_upl_abort_range ( pageInArgsPtr->a_pl,
pageInArgsPtr->a_pl_offset,
pageInArgsPtr->a_size,
UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY );
}
error = EINVAL;
DebugLog ( ( "CDDA_PageIn: trying to page in from a negative offset.\n" ) );
return ( error );
}
if ( pageInArgsPtr->a_f_offset > numBytes )
{
if ( !nocommit )
{
ubc_upl_abort_range ( pageInArgsPtr->a_pl,
pageInArgsPtr->a_pl_offset,
pageInArgsPtr->a_size,
UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY );
}
return ( error );
}
if ( cddaNodePtr->nodeType == kAppleCDDAXMLFileType )
{
kern_return_t kret = 0;
vm_offset_t vmOffsetPtr = 0;
off_t amountToCopy = 0;
kret = ubc_upl_map ( pageInArgsPtr->a_pl, &vmOffsetPtr );
if ( kret != KERN_SUCCESS || vmOffsetPtr == 0 )
{
panic ( "CDDA_PageIn: error mapping buffer into kernel space!" );
}
bzero ( ( caddr_t )( vmOffsetPtr + pageInArgsPtr->a_pl_offset ), PAGE_SIZE );
amountToCopy = ulmin ( PAGE_SIZE, numBytes - pageInArgsPtr->a_f_offset );
bcopy ( &cddaNodePtr->u.xmlFile.fileDataPtr[pageInArgsPtr->a_f_offset],
( void * ) vmOffsetPtr,
amountToCopy );
kret = ubc_upl_unmap ( pageInArgsPtr->a_pl );
if ( kret != KERN_SUCCESS )
{
panic ( "CDDA_PageIn: error unmapping buffer from kernel space!" );
}
if ( !nocommit )
{
ubc_upl_commit_range ( pageInArgsPtr->a_pl,
pageInArgsPtr->a_pl_offset,
PAGE_SIZE,
UPL_COMMIT_FREE_ON_EMPTY | UPL_COMMIT_CLEAR_DIRTY );
}
return 0;
}
else if ( cddaNodePtr->nodeType == kAppleCDDATrackType )
{
UInt32 headerSize = 0;
UInt32 blockNumber = 0;
UInt32 count = 0;
off_t offset = 0;
off_t sectorOffset = 0;
off_t residual = 0;
kern_return_t kret = 0;
vm_offset_t vmOffsetPtr = 0;
struct buf * bufPtr = NULL;
residual = pageInArgsPtr->a_size;
offset = pageInArgsPtr->a_f_offset;
if ( offset > cddaNodePtr->u.file.nodeInfoPtr->numBytes )
{
DebugLog ( ( "CDDA_PageIn: Can't read past end of file..." ) );
return ( 0 );
}
headerSize = sizeof ( cddaNodePtr->u.file.aiffHeader );
kret = ubc_upl_map ( pageInArgsPtr->a_pl, &vmOffsetPtr );
if ( kret != KERN_SUCCESS || vmOffsetPtr == 0 )
{
panic ( "CDDA_PageIn: error mapping buffer into kernel space!" );
}
if ( offset < headerSize )
{
off_t amountToCopy = 0;
amountToCopy = ulmin ( pageInArgsPtr->a_size, headerSize - offset );
bcopy ( &cddaNodePtr->u.file.aiffHeader.u.alignedHeader.filler[pageInArgsPtr->a_f_offset],
( void * ) vmOffsetPtr,
amountToCopy );
offset += amountToCopy;
residual -= amountToCopy;
}
if ( ( residual > 0 ) &&
( offset < cddaNodePtr->u.file.nodeInfoPtr->numBytes ) )
{
offset -= headerSize;
sectorOffset = offset % kPhysicalMediaBlockSize;
blockNumber = ( offset / kPhysicalMediaBlockSize ) + cddaNodePtr->u.file.nodeInfoPtr->LBA;
if ( sectorOffset != 0 )
{
count = ulmin ( residual, ( kPhysicalMediaBlockSize - sectorOffset ) );
count = ulmin ( count, cddaNodePtr->u.file.nodeInfoPtr->numBytes - offset );
error = bread ( cddaNodePtr->blockDeviceVNodePtr,
blockNumber,
kPhysicalMediaBlockSize,
NOCRED,
&bufPtr );
if ( error != 0 )
{
brelse ( bufPtr );
return ( error );
}
bcopy ( bufPtr->b_data + sectorOffset, ( void * ) vmOffsetPtr + offset + headerSize, count );
offset += count;
residual -= count;
SET ( bufPtr->b_flags, B_INVAL );
brelse ( bufPtr );
blockNumber++;
}
while ( ( residual > kPhysicalMediaBlockSize ) &&
( offset < cddaNodePtr->u.file.nodeInfoPtr->numBytes ) )
{
UInt32 blocksToRead = 0;
if ( residual > kMaxBytesPerRead )
{
blocksToRead = kMaxBlocksPerRead;
count = kMaxBytesPerRead;
}
else
{
blocksToRead = residual / kPhysicalMediaBlockSize;
count = blocksToRead * kPhysicalMediaBlockSize;
}
error = bread ( cddaNodePtr->blockDeviceVNodePtr,
blockNumber,
count,
NOCRED,
&bufPtr );
if ( error != 0 )
{
brelse ( bufPtr );
return ( error );
}
count = ulmin ( count, cddaNodePtr->u.file.nodeInfoPtr->numBytes - offset );
bcopy ( bufPtr->b_data, ( void * ) vmOffsetPtr + offset + headerSize, count );
offset += count;
residual -= count;
SET ( bufPtr->b_flags, B_INVAL );
brelse ( bufPtr );
blockNumber += blocksToRead;
}
if ( ( residual > 0 ) &&
( offset < cddaNodePtr->u.file.nodeInfoPtr->numBytes ) )
{
count = ulmin ( residual, cddaNodePtr->u.file.nodeInfoPtr->numBytes - offset );
error = bread ( cddaNodePtr->blockDeviceVNodePtr,
blockNumber,
kPhysicalMediaBlockSize,
NOCRED,
&bufPtr );
if ( error != 0 )
{
brelse ( bufPtr );
return ( error );
}
bcopy ( bufPtr->b_data, ( void * ) vmOffsetPtr + offset + headerSize, count );
offset += count;
residual -= count;
brelse ( bufPtr );
}
}
kret = ubc_upl_unmap ( pageInArgsPtr->a_pl );
if ( kret != KERN_SUCCESS )
{
panic ( "CDDA_PageIn: error unmapping buffer from kernel space!" );
}
if ( !nocommit )
{
ubc_upl_commit_range ( pageInArgsPtr->a_pl,
pageInArgsPtr->a_pl_offset,
pageInArgsPtr->a_size,
UPL_COMMIT_FREE_ON_EMPTY | UPL_COMMIT_CLEAR_DIRTY );
}
}
DebugLog ( ( "CDDA_PageIn: exiting...\n" ) );
return ( error );
}
int
CDDA_GetAttributes ( struct vop_getattr_args * getAttrArgsPtr )
{
struct vnode * vNodePtr = NULL;
struct vattr * attributesPtr = NULL;
AppleCDDANodePtr cddaNodePtr = NULL;
AppleCDDAMountPtr cddaMountPtr = NULL;
DebugLog ( ( "CDDA_GetAttributes: Entering.\n" ) );
DebugAssert ( ( getAttrArgsPtr != NULL ) );
vNodePtr = getAttrArgsPtr->a_vp;
attributesPtr = getAttrArgsPtr->a_vap;
DebugAssert ( ( vNodePtr != NULL ) );
DebugAssert ( ( attributesPtr != NULL ) );
cddaMountPtr = VFSTOCDDA ( vNodePtr->v_mount );
cddaNodePtr = VTOCDDA ( vNodePtr );
DebugAssert ( ( cddaNodePtr != NULL ) );
DebugAssert ( ( cddaMountPtr != NULL ) );
DebugLog ( ( "nodeID = %ld.\n", cddaNodePtr->nodeID ) );
attributesPtr->va_fsid = vNodePtr->v_mount->mnt_stat.f_fsid.val[0];
attributesPtr->va_fileid = cddaNodePtr->nodeID; attributesPtr->va_type = vNodePtr->v_type; attributesPtr->va_blocksize = kPhysicalMediaBlockSize;
attributesPtr->va_atime = cddaMountPtr->mountTime; attributesPtr->va_mtime = cddaMountPtr->mountTime; attributesPtr->va_ctime = cddaMountPtr->mountTime;
attributesPtr->va_uid = kUnknownUserID; attributesPtr->va_gid = kUnknownGroupID; attributesPtr->va_gen = 0;
attributesPtr->va_flags = 0;
attributesPtr->va_rdev = NULL;
attributesPtr->va_mode = S_IRUSR | S_IRGRP | S_IROTH;
if ( vNodePtr->v_flag & VROOT )
{
attributesPtr->va_mode |= S_IFDIR; attributesPtr->va_mode |= S_IXUSR | S_IXGRP | S_IXOTH; attributesPtr->va_nlink = kAppleCDDANumberOfRootDirReferences;
attributesPtr->va_bytes = attributesPtr->va_size = ( cddaNodePtr->u.directory.entryCount ) * sizeof ( struct dirent );
}
else
{
attributesPtr->va_mode |= S_IFREG; attributesPtr->va_nlink = kAppleCDDANumberOfFileReferences;
if ( cddaNodePtr->nodeType == kAppleCDDATrackType )
{
attributesPtr->va_bytes = attributesPtr->va_size = cddaNodePtr->u.file.nodeInfoPtr->numBytes;
}
else if ( cddaNodePtr->nodeType == kAppleCDDAXMLFileType )
{
attributesPtr->va_bytes = attributesPtr->va_size = cddaNodePtr->u.xmlFile.fileSize;
}
}
DebugLog ( ( "CDDA_GetAttributes: exiting...\n" ) );
return ( 0 );
}
int
CDDA_GetAttributesList ( struct vop_getattrlist_args * attrListArgsPtr )
{
struct vnode * vNodePtr = NULL;
AppleCDDANodePtr cddaNodePtr = NULL;
struct attrlist * attributesListPtr = NULL;
int error = 0;
UInt32 fixedblocksize;
UInt32 attrblocksize;
UInt32 attrbufsize;
void * attrbufptr;
void * attrptr;
void * varptr;
DebugLog ( ( "CDDA_GetAttributesList: Entering.\n" ) );
DebugAssert ( ( attrListArgsPtr != NULL ) );
vNodePtr = attrListArgsPtr->a_vp;
attributesListPtr = attrListArgsPtr->a_alist;
DebugAssert ( ( vNodePtr != NULL ) );
DebugAssert ( ( attributesListPtr != NULL ) );
cddaNodePtr = VTOCDDA ( vNodePtr );
DebugAssert ( ( cddaNodePtr != NULL ) );
DebugAssert ( ( ap->a_uio->uio_rw == UIO_READ ) );
if ( ( attributesListPtr->bitmapcount != 5 ) ||
( ( attributesListPtr->commonattr & ~kAppleCDDACommonAttributesValidMask ) != 0 ) ||
( ( attributesListPtr->volattr & ~kAppleCDDAVolumeAttributesValidMask ) != 0 ) ||
( ( attributesListPtr->dirattr & ~kAppleCDDADirectoryAttributesValidMask ) != 0 ) ||
( ( attributesListPtr->fileattr & ~kAppleCDDAFileAttributesValidMask ) != 0 ) ||
( ( attributesListPtr->forkattr & ~kAppleCDDAForkAttributesValidMask ) != 0) )
{
DebugLog ( ( "CDDA_GetAttributesList: bad attrlist\n" ) );
return EOPNOTSUPP;
}
if ( ( attributesListPtr->volattr != 0 ) && ( ( ( attributesListPtr->volattr & ATTR_VOL_INFO ) == 0 ) ||
( attributesListPtr->dirattr != 0 ) || ( attributesListPtr->fileattr != 0 ) || ( attributesListPtr->forkattr != 0 ) ) )
{
DebugLog ( ( "CDDA_GetAttributesList: conflicting information requested\n" ) );
return EINVAL;
}
fixedblocksize = CalculateAttributeBlockSize ( attributesListPtr );
attrblocksize = fixedblocksize + ( sizeof ( UInt32 ) );
if ( attributesListPtr->commonattr & ATTR_CMN_NAME )
attrblocksize += kCDDAMaxFileNameBytes + 1;
if ( attributesListPtr->volattr & ATTR_VOL_MOUNTPOINT )
attrblocksize += PATH_MAX;
if ( attributesListPtr->volattr & ATTR_VOL_NAME )
attrblocksize += kCDDAMaxFileNameBytes + 1;
attrbufsize = MIN ( attrListArgsPtr->a_uio->uio_resid, attrblocksize );
DebugLog ( ( "CDDA_GetAttributesList: allocating Ox%X byte buffer (Ox%X + Ox%X) for attributes...\n",
attrblocksize, fixedblocksize, attrblocksize - fixedblocksize ) );
MALLOC ( attrbufptr, void *, attrblocksize, M_TEMP, M_WAITOK );
attrptr = attrbufptr;
*( ( UInt32 * ) attrptr ) = 0;
++( ( UInt32 * ) attrptr );
varptr = ( ( char * ) attrptr ) + fixedblocksize;
DebugLog ( ( "CDDA_GetAttributesList: attrptr = 0x%08X, varptr = 0x%08X...\n", ( u_int ) attrptr, ( u_int ) varptr ) );
PackAttributesBlock ( attributesListPtr, vNodePtr, &attrptr, &varptr );
DebugLog ( ( "CDDA_GetAttributesList: calculating MIN\n" ) );
attrbufsize = MIN ( attrbufsize, ( u_int ) varptr - ( u_int ) attrbufptr );
DebugLog ( ( "CDDA_GetAttributesList: setting attrbufsize = %ld\n", attrbufsize ) );
*( ( UInt32 * ) attrbufptr ) = attrbufsize;
DebugLog ( ( "CDDA_GetAttributesList: copying %ld bytes to user address 0x%08X.\n",
( UInt32 ) attrbufsize, ( u_int ) attrListArgsPtr->a_uio->uio_iov->iov_base ) );
error = uiomove ( ( caddr_t ) attrbufptr, attrbufsize, attrListArgsPtr->a_uio );
if ( error != 0 )
{
DebugLog ( ( "CDDA_GetAttributesList: error %d on uiomove.\n", error ) );
}
DebugLog ( ( "CDDA_GetAttributesList: calling FREE\n" ) );
FREE ( attrbufptr, M_TEMP );
return error;
}
int
CDDA_Inactive ( struct vop_inactive_args * inactiveArgsPtr )
{
DebugLog ( ( "CDDA_Inactive: Entering.\n" ) );
DebugAssert ( ( inactiveArgsPtr != NULL ) );
( void ) nop_inactive ( inactiveArgsPtr );
DebugLog ( ( "CDDA_Inactive: exiting...\n" ) );
return ( 0 );
}
#if RENAME_SUPPORTED
int
CDDA_Rename ( struct vop_rename_args * renameArgsPtr )
{
struct vnode * targetVNodePtr = NULL;
struct vnode * targetParentVNodePtr = NULL;
struct vnode * sourceVNodePtr = NULL;
struct vnode * sourceParentVNodePtr = NULL;
struct componentname * targetComponentNamePtr = NULL;
struct componentname * sourceComponentNamePtr = NULL;
struct proc * procPtr = NULL;
AppleCDDAMountPtr cddaMountPtr = NULL;
AppleCDDANodePtr sourceCDDANodePtr = NULL;
AppleCDDANodePtr sourceParentCDDANodePtr = NULL;
AppleCDDANodeInfoPtr nodeInfoPtr = NULL;
int retval = 0;
struct timeval tv;
struct timespec timespec;
DebugLog ( ( "CDDA_Rename: Entering.\n" ) );
DebugAssert ( ( renameArgsPtr != NULL ) );
targetVNodePtr = renameArgsPtr->a_tvp;
targetParentVNodePtr = renameArgsPtr->a_tdvp;
sourceVNodePtr = renameArgsPtr->a_fvp;
sourceParentVNodePtr = renameArgsPtr->a_fdvp;
targetComponentNamePtr = renameArgsPtr->a_tcnp;
sourceComponentNamePtr = renameArgsPtr->a_fcnp;
DebugAssert ( ( targetVNodePtr != NULL ) );
DebugAssert ( ( targetParentVNodePtr != NULL ) );
DebugAssert ( ( sourceVNodePtr != NULL ) );
DebugAssert ( ( sourceParentVNodePtr != NULL ) );
DebugAssert ( ( targetComponentNamePtr != NULL ) );
DebugAssert ( ( sourceComponentNamePtr != NULL ) );
procPtr = sourceComponentNamePtr->cn_proc;
DebugAssert ( ( procPtr != NULL ) );
if ( ( ( targetComponentNamePtr->cn_flags & HASBUF ) == 0 ) ||
( ( sourceComponentNamePtr->cn_flags & HASBUF ) == 0 ) )
panic ( "CDDA_Rename: no name" );
if ( targetVNodePtr != NULL )
{
DebugLog ( ( "CDDA_Rename: sourceVNodePtr != targetVNodePtr.\n" ) );
retval = EINVAL;
goto Exit;
}
sourceCDDANodePtr = VTOCDDA ( sourceVNodePtr );
sourceParentCDDANodePtr = VTOCDDA ( sourceParentVNodePtr );
if ( sourceCDDANodePtr->nodeType == kAppleCDDADirectoryType )
{
DebugLog ( ( "CDDA_Rename: sourceCDDANodePtr->nodeType == kAppleCDDADirectoryType.\n" ) );
retval = EINVAL;
goto Exit;
}
if ( sourceCDDANodePtr->nodeType == kAppleCDDAXMLFileType )
{
DebugLog ( ( "CDDA_Rename: sourceCDDANodePtr->nodeType == kAppleCDDAXMLFileType.\n" ) );
retval = EPERM;
goto Exit;
}
if ( targetComponentNamePtr->cn_nameptr )
{
char buffer[3];
char * ptr;
char * ptr2;
UInt32 size;
UInt8 value;
ptr = strchr ( targetComponentNamePtr->cn_nameptr, ' ' );
if ( ptr == NULL )
{
DebugLog ( ( "CDDA_Rename: Need space between number and name.\n" ) );
retval = EINVAL;
goto Exit;
}
size = ( UInt32 ) ptr - ( UInt32 ) targetComponentNamePtr->cn_nameptr;
if ( size < 1 )
{
DebugLog ( ( "CDDA_Rename: Amount of data to copy is nothing, bail\n" ) );
retval = EINVAL;
goto Exit;
}
strncpy ( buffer, targetComponentNamePtr->cn_nameptr, size );
buffer[size] = 0;
value = atoi ( buffer );
if ( value != sourceCDDANodePtr->u.file.nodeInfoPtr->trackDescriptor.point )
{
DebugLog ( ( "CDDA_Rename: Name is invalid\n" ) );
retval = EINVAL;
goto Exit;
}
ptr = strchr ( targetComponentNamePtr->cn_nameptr, '.' );
if ( ptr == NULL )
{
DebugLog ( ( "CDDA_Rename: No .aiff at the end\n" ) );
retval = EINVAL;
goto Exit;
}
ptr2 = strchr ( ptr + 1, '.' );
while ( ptr2 != NULL )
{
DebugLog ( ( "CDDA_Rename: In while loop\n" ) );
ptr = ptr2;
ptr2 = strchr ( ptr2 + 1, '.' );
}
size = ( UInt32 ) ptr - ( UInt32 ) targetComponentNamePtr->cn_nameptr + strlen ( ".aiff" );
if ( size != strlen ( targetComponentNamePtr->cn_nameptr ) )
{
DebugLog ( ( "CDDA_Rename: .aiff is not at the ending\n" ) );
retval = EINVAL;
goto Exit;
}
}
cache_purge ( sourceVNodePtr );
DebugLog ( ( "CDDA_Rename: finished cach_purge.\n" ) );
nodeInfoPtr = sourceCDDANodePtr->u.file.nodeInfoPtr;
FREE ( nodeInfoPtr->name, M_TEMP );
DebugLog ( ( "CDDA_Rename: FREE'd name.\n" ) );
MALLOC ( nodeInfoPtr->name, char *, strlen ( targetComponentNamePtr->cn_nameptr ) + 1, M_TEMP, M_WAITOK );
strcpy ( nodeInfoPtr->name, targetComponentNamePtr->cn_nameptr );
nodeInfoPtr->nameSize = strlen ( targetComponentNamePtr->cn_nameptr );
DebugLog ( ( "CDDA_Rename: finished strcpy of name.\n" ) );
tv = time;
TIMEVAL_TO_TIMESPEC ( &tv, ×pec );
cddaMountPtr = VFSTOCDDA ( sourceVNodePtr->v_mount );
cddaMountPtr->mountTime = timespec;
Exit:
if ( targetVNodePtr != NULL )
{
vput ( targetVNodePtr );
DebugLog ( ( "CDDA_Rename: vput of targetVNodePtr done.\n" ) );
}
vput ( targetParentVNodePtr );
DebugLog ( ( "CDDA_Rename: vput of targetParentVNodePtr done.\n" ) );
vrele ( sourceParentVNodePtr );
DebugLog ( ( "CDDA_Rename: vrele of sourceParentVNodePtr done.\n" ) );
vrele ( sourceVNodePtr );
DebugLog ( ( "CDDA_Rename: vrele of sourceVNodePtr done.\n" ) );
return retval;
}
#endif
int
CDDA_Remove ( struct vop_remove_args * removeArgsPtr )
{
DebugLog ( ( "CDDA_Remove: Entering.\n" ) );
DebugAssert ( ( removeArgsPtr != NULL ) );
( void ) nop_remove ( removeArgsPtr );
DebugLog ( ( "CDDA_Remove: exiting...\n" ) );
return ( EROFS );
}
int
CDDA_RmDir ( struct vop_rmdir_args * removeDirArgsPtr )
{
DebugLog ( ( "CDDA_RmDir: Entering.\n" ) );
DebugAssert ( ( removeDirArgsPtr != NULL ) );
( void ) nop_rmdir ( removeDirArgsPtr );
DebugLog ( ( "CDDA_RmDir: exiting...\n" ) );
return ( EROFS );
}
int
CDDA_Reclaim ( struct vop_reclaim_args * reclaimArgsPtr )
{
int error = 0;
DebugLog ( ( "CDDA_Reclaim: Entering.\n" ) );
DebugAssert ( ( reclaimArgsPtr != NULL ) );
error = DisposeCDDANode ( reclaimArgsPtr->a_vp, reclaimArgsPtr->a_p );
DebugLog ( ( "CDDA_Reclaim: exiting...\n" ) );
return ( error );
}
int
CDDA_Access ( struct vop_access_args * accessArgsPtr )
{
AppleCDDANodePtr cddaNodePtr = NULL;
struct ucred * cred = NULL;
mode_t mode = 0;
int error = 0;
DebugLog ( ( "CDDA_Access: Entering.\n" ) );
DebugAssert ( ( accessArgsPtr != NULL ) );
cred = accessArgsPtr->a_cred;
mode = accessArgsPtr->a_mode;
cddaNodePtr = VTOCDDA ( accessArgsPtr->a_vp );
DebugAssert ( ( cddaNodePtr != NULL ) );
if ( mode & VWRITE )
{
if ( accessArgsPtr->a_vp->v_mount->mnt_flag & MNT_RDONLY )
{
return ( EROFS );
}
else
{
DebugLog ( ( "Error: this filesystem is read-only, but isn't marked read-only" ) );
panic ( "Read-Only filesystem" );
}
}
if ( cred->cr_uid == 0 )
{
error = 0;
}
error = 0;
DebugLog ( ( "CDDA_Access: exiting...\n" ) );
return ( error );
}
int
CDDA_BlockToOffset ( struct vop_blktooff_args * blockToOffsetArgsPtr )
{
DebugLog ( ( "CDDA_BlockToOffset: Entering.\n" ) );
DebugAssert ( ( blockToOffsetArgsPtr != NULL ) );
if ( blockToOffsetArgsPtr->a_vp == NULL )
{
DebugLog ( ( "CDDA_BlockToOffset: incoming vnode is NULL.\n" ) );
return ( EINVAL );
}
*( blockToOffsetArgsPtr->a_offset ) =
( off_t ) ( blockToOffsetArgsPtr->a_lblkno * PAGE_SIZE );
DebugLog ( ( "CDDA_BlockToOffset: exiting...\n" ) );
return ( 0 );
}
int
CDDA_OffsetToBlock ( struct vop_offtoblk_args * offsetToBlockArgsPtr )
{
DebugLog ( ( "CDDA_OffsetToBlock: Entering.\n" ) );
DebugAssert ( ( offsetToBlockArgsPtr != NULL ) );
if ( offsetToBlockArgsPtr->a_vp == NULL )
{
DebugLog ( ( "CDDA_OffsetToBlock: incoming vnode is NULL.\n" ) );
return ( EINVAL );
}
*( offsetToBlockArgsPtr->a_lblkno ) = ( offsetToBlockArgsPtr->a_offset / PAGE_SIZE );
DebugLog ( ( "CDDA_OffsetToBlock: exiting...\n" ) );
return ( 0 );
}
int
CDDA_Pathconf ( struct vop_pathconf_args * pathConfArgsPtr )
{
int returnValue = 0;
DebugLog ( ( "CDDA_Pathconf: Entering.\n" ) );
DebugAssert ( ( pathConfArgsPtr != NULL ) );
switch ( pathConfArgsPtr->a_name )
{
case _PC_LINK_MAX:
*pathConfArgsPtr->a_retval = 1;
break;
case _PC_NAME_MAX:
*pathConfArgsPtr->a_retval = NAME_MAX;
break;
case _PC_PATH_MAX:
*pathConfArgsPtr->a_retval = PATH_MAX;
break;
case _PC_CHOWN_RESTRICTED:
*pathConfArgsPtr->a_retval = 1;
break;
case _PC_NO_TRUNC:
*pathConfArgsPtr->a_retval = 0;
break;
default:
returnValue = EINVAL;
break;
}
DebugLog ( ( "CDDA_Pathconf: exiting with returnValue = %d.\n", returnValue ) );
return ( returnValue );
}
int
CDDA_Lock ( struct vop_lock_args * lockArgsPtr )
{
struct vnode * vNodePtr = NULL;
AppleCDDANodePtr cddaNodePtr = NULL;
int error = 0;
DebugLog ( ( "CDDA_Lock: Entering.\n" ) );
DebugAssert ( ( lockArgsPtr != NULL ) );
vNodePtr = lockArgsPtr->a_vp;
DebugAssert ( ( vNodePtr != NULL ) );
cddaNodePtr = VTOCDDA ( vNodePtr );
DebugAssert ( ( cddaNodePtr != NULL ) );
error = lockmgr ( &cddaNodePtr->lock, lockArgsPtr->a_flags,
&vNodePtr->v_interlock, lockArgsPtr->a_p );
if ( error != 0 )
{
if ( ( lockArgsPtr->a_flags & LK_NOWAIT ) == 0 )
{
DebugLog ( ( "CDDA_Lock: error %d trying to lock vnode (flags = 0x%08X).\n", error, lockArgsPtr->a_flags ) );
}
}
DebugLog ( ( "CDDA_Lock: exiting...\n" ) );
return ( error );
}
int
CDDA_Unlock ( struct vop_unlock_args * unlockArgsPtr )
{
struct vnode * vNodePtr = NULL;
AppleCDDANodePtr cddaNodePtr = NULL;
int error = 0;
DebugLog ( ( "CDDA_Unlock: Entering.\n" ) );
DebugAssert ( ( unlockArgsPtr != NULL ) );
vNodePtr = unlockArgsPtr->a_vp;
DebugAssert ( ( vNodePtr != NULL ) );
cddaNodePtr = VTOCDDA ( vNodePtr );
DebugAssert ( ( cddaNodePtr != NULL ) );
error = lockmgr ( &cddaNodePtr->lock, unlockArgsPtr->a_flags | LK_RELEASE,
&vNodePtr->v_interlock, unlockArgsPtr->a_p );
if ( error != 0 )
{
DebugLog ( ( "CDDA_Unlock: error %d trying to unlock vnode (flags = 0x%08X).\n", error, unlockArgsPtr->a_flags ) );
}
DebugLog ( ( "CDDA_Unlock: exiting...\n" ) );
return ( error );
}
int
CDDA_IsLocked ( struct vop_islocked_args * isLockedArgsPtr )
{
struct vnode * vNodePtr = NULL;
AppleCDDANodePtr cddaNodePtr = NULL;
int lockStatus = 0;
DebugLog ( ( "CDDA_IsLocked: Entering.\n" ) );
DebugAssert ( ( isLockedArgsPtr != NULL ) );
vNodePtr = isLockedArgsPtr->a_vp;
DebugAssert ( ( vNodePtr != NULL ) );
cddaNodePtr = VTOCDDA ( vNodePtr );
DebugAssert ( ( cddaNodePtr != NULL ) );
lockStatus = lockstatus ( &cddaNodePtr->lock );
DebugLog ( ( "CDDA_IsLocked: exiting...\n" ) );
return ( lockStatus );
}
int
CDDA_Print ( struct vop_print_args * printArgsPtr )
{
#if DEBUG
DebugAssert ( ( printArgsPtr != NULL ) );
#else
#pragma unused ( printArgsPtr )
#endif
DebugLog ( ( "CDDA_Print: Entering.\n" ) );
DebugLog ( ( "CDDA_Print: exiting...\n" ) );
return ( 0 );
}
int
CDDA_VFree ( struct vop_vfree_args * vFreeArgsPtr )
{
#if DEBUG
DebugAssert ( ( vFreeArgsPtr != NULL ) );
#else
#pragma unused ( vFreeArgsPtr )
#endif
DebugLog ( ( "CDDA_VFree: Entering.\n" ) );
DebugLog ( ( "CDDA_VFree: exiting...\n" ) );
return ( 0 );
}
int ( **gCDDA_VNodeOp_p )( void * );
#define VOPFUNC int ( * )( void * )
#if 0
#pragma mark -
#endif
struct vnodeopv_entry_desc gCDDA_VNodeOperationEntries[] =
{
{ &vop_default_desc, ( VOPFUNC ) vn_default_error },
{ &vop_lookup_desc, ( VOPFUNC ) CDDA_Lookup }, { &vop_create_desc, ( VOPFUNC ) err_create }, { &vop_mknod_desc, ( VOPFUNC ) err_mknod }, { &vop_open_desc, ( VOPFUNC ) CDDA_Open }, { &vop_close_desc, ( VOPFUNC ) CDDA_Close }, { &vop_access_desc, ( VOPFUNC ) CDDA_Access }, { &vop_getattr_desc, ( VOPFUNC ) CDDA_GetAttributes }, { &vop_setattr_desc, ( VOPFUNC ) nop_setattr }, { &vop_read_desc, ( VOPFUNC ) CDDA_Read }, { &vop_write_desc, ( VOPFUNC ) err_write }, { &vop_ioctl_desc, ( VOPFUNC ) err_ioctl }, { &vop_select_desc, ( VOPFUNC ) err_select }, { &vop_exchange_desc, ( VOPFUNC ) err_exchange }, { &vop_mmap_desc, ( VOPFUNC ) err_mmap }, { &vop_fsync_desc, ( VOPFUNC ) nop_fsync }, { &vop_seek_desc, ( VOPFUNC ) err_seek }, { &vop_remove_desc, ( VOPFUNC ) CDDA_Remove }, { &vop_link_desc, ( VOPFUNC ) err_link }, #if RENAME_SUPPORTED
{ &vop_rename_desc, ( VOPFUNC ) CDDA_Rename }, #else
{ &vop_rename_desc, ( VOPFUNC ) err_rename }, #endif
{ &vop_mkdir_desc, ( VOPFUNC ) err_mkdir }, { &vop_rmdir_desc, ( VOPFUNC ) CDDA_RmDir }, { &vop_getattrlist_desc, ( VOPFUNC ) CDDA_GetAttributesList }, { &vop_setattrlist_desc, ( VOPFUNC ) err_setattrlist }, { &vop_symlink_desc, ( VOPFUNC ) err_symlink }, { &vop_readdir_desc, ( VOPFUNC ) CDDA_ReadDir }, { &vop_readdirattr_desc, ( VOPFUNC ) err_readdirattr }, { &vop_readlink_desc, ( VOPFUNC ) err_readlink }, { &vop_abortop_desc, ( VOPFUNC ) err_abortop }, { &vop_inactive_desc, ( VOPFUNC ) CDDA_Inactive }, { &vop_reclaim_desc, ( VOPFUNC ) CDDA_Reclaim }, { &vop_lock_desc, ( VOPFUNC ) CDDA_Lock }, { &vop_unlock_desc, ( VOPFUNC ) CDDA_Unlock }, { &vop_bmap_desc, ( VOPFUNC ) err_bmap }, { &vop_strategy_desc, ( VOPFUNC ) err_strategy }, { &vop_print_desc, ( VOPFUNC ) CDDA_Print }, { &vop_islocked_desc, ( VOPFUNC ) CDDA_IsLocked }, { &vop_pathconf_desc, ( VOPFUNC ) CDDA_Pathconf }, { &vop_advlock_desc, ( VOPFUNC ) err_advlock }, { &vop_reallocblks_desc, ( VOPFUNC ) err_reallocblks }, { &vop_truncate_desc, ( VOPFUNC ) err_truncate }, { &vop_allocate_desc, ( VOPFUNC ) err_allocate }, { &vop_update_desc, ( VOPFUNC ) nop_update }, { &vop_bwrite_desc, ( VOPFUNC ) err_bwrite }, { &vop_pagein_desc, ( VOPFUNC ) CDDA_PageIn }, { &vop_pageout_desc, ( VOPFUNC ) err_pageout }, { &vop_blktooff_desc, ( VOPFUNC ) CDDA_BlockToOffset }, { &vop_offtoblk_desc, ( VOPFUNC ) CDDA_OffsetToBlock }, { &vop_cmap_desc, ( VOPFUNC ) err_cmap }, { NULL, ( VOPFUNC ) NULL }
};
struct vnodeopv_desc gCDDA_VNodeOperationsDesc =
{
&gCDDA_VNodeOp_p,
gCDDA_VNodeOperationEntries
};